humane-proxy 0.2.3__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. {humane_proxy-0.2.3/humane_proxy.egg-info → humane_proxy-0.3.1}/PKG-INFO +132 -12
  2. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/README.md +119 -10
  3. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/__init__.py +1 -1
  4. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/api/admin.py +166 -2
  5. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/embedding_classifier.py +104 -11
  6. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/pipeline.py +14 -3
  7. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/cli.py +1 -1
  8. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/config.py +6 -0
  9. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/config.yaml +44 -0
  10. humane_proxy-0.3.1/humane_proxy/escalation/local_db.py +68 -0
  11. humane_proxy-0.3.1/humane_proxy/integrations/autogen.py +160 -0
  12. humane_proxy-0.3.1/humane_proxy/integrations/crewai.py +131 -0
  13. humane_proxy-0.3.1/humane_proxy/integrations/llamaindex.py +138 -0
  14. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/mcp_server.py +1 -6
  15. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/middleware/interceptor.py +1 -1
  16. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/risk/trajectory.py +63 -11
  17. humane_proxy-0.3.1/humane_proxy/storage/__init__.py +15 -0
  18. humane_proxy-0.3.1/humane_proxy/storage/base.py +75 -0
  19. humane_proxy-0.3.1/humane_proxy/storage/factory.py +75 -0
  20. humane_proxy-0.3.1/humane_proxy/storage/postgres.py +212 -0
  21. humane_proxy-0.3.1/humane_proxy/storage/redis.py +193 -0
  22. humane_proxy-0.3.1/humane_proxy/storage/sqlite.py +242 -0
  23. {humane_proxy-0.2.3 → humane_proxy-0.3.1/humane_proxy.egg-info}/PKG-INFO +132 -12
  24. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy.egg-info/SOURCES.txt +13 -0
  25. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy.egg-info/requires.txt +17 -1
  26. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/pyproject.toml +18 -2
  27. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/server.json +3 -3
  28. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_embedding_classifier.py +8 -2
  29. humane_proxy-0.3.1/tests/test_embedding_singleton.py +77 -0
  30. humane_proxy-0.3.1/tests/test_integrations_smoke.py +76 -0
  31. humane_proxy-0.3.1/tests/test_self_harm_threshold.py +51 -0
  32. humane_proxy-0.3.1/tests/test_storage_backends.py +81 -0
  33. humane_proxy-0.3.1/tests/test_trajectory.py +180 -0
  34. humane_proxy-0.2.3/humane_proxy/escalation/local_db.py +0 -170
  35. humane_proxy-0.2.3/tests/test_trajectory.py +0 -108
  36. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/LICENSE +0 -0
  37. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/NOTICE +0 -0
  38. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/api/__init__.py +0 -0
  39. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/__init__.py +0 -0
  40. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/heuristics.py +0 -0
  41. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/models.py +0 -0
  42. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/stage3/__init__.py +0 -0
  43. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/stage3/base.py +0 -0
  44. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/stage3/llamaguard.py +0 -0
  45. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/stage3/openai_chat.py +0 -0
  46. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/classifiers/stage3/openai_moderation.py +0 -0
  47. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/escalation/__init__.py +0 -0
  48. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/escalation/router.py +0 -0
  49. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/escalation/webhooks.py +0 -0
  50. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/integrations/__init__.py +0 -0
  51. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/integrations/langchain.py +0 -0
  52. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/middleware/__init__.py +0 -0
  53. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy/risk/__init__.py +0 -0
  54. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy.egg-info/dependency_links.txt +0 -0
  55. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy.egg-info/entry_points.txt +0 -0
  56. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/humane_proxy.egg-info/top_level.txt +0 -0
  57. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/setup.cfg +0 -0
  58. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_admin_api.py +0 -0
  59. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_care_response.py +0 -0
  60. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_cli.py +0 -0
  61. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_config.py +0 -0
  62. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_enhanced_webhooks.py +0 -0
  63. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_heuristics.py +0 -0
  64. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_interceptor.py +0 -0
  65. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_local_db.py +0 -0
  66. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_models.py +0 -0
  67. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_pipeline.py +0 -0
  68. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_router.py +0 -0
  69. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_stage3.py +0 -0
  70. {humane_proxy-0.2.3 → humane_proxy-0.3.1}/tests/test_webhooks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: humane-proxy
3
- Version: 0.2.3
3
+ Version: 0.3.1
4
4
  Summary: Lightweight, plug-and-play AI safety middleware that protects humans.
5
5
  Author-email: Vishisht Mishra <Vishisht16@users.noreply.github.com>
6
6
  License: Apache-2.0
@@ -40,8 +40,19 @@ Requires-Dist: humane-proxy[mcp]; extra == "langchain"
40
40
  Requires-Dist: langchain-mcp-adapters>=0.1.0; extra == "langchain"
41
41
  Provides-Extra: webhooks
42
42
  Requires-Dist: httpx>=0.24.0; extra == "webhooks"
43
+ Provides-Extra: redis
44
+ Requires-Dist: redis>=5.0; extra == "redis"
45
+ Provides-Extra: postgres
46
+ Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
47
+ Requires-Dist: psycopg_pool>=3.1; extra == "postgres"
48
+ Provides-Extra: llamaindex
49
+ Requires-Dist: llama-index-core>=0.10; extra == "llamaindex"
50
+ Provides-Extra: crewai
51
+ Requires-Dist: crewai[tools]>=0.80; extra == "crewai"
52
+ Provides-Extra: autogen
53
+ Requires-Dist: autogen-agentchat>=0.4; extra == "autogen"
43
54
  Provides-Extra: all
44
- Requires-Dist: humane-proxy[langchain,mcp,ml]; extra == "all"
55
+ Requires-Dist: humane-proxy[autogen,crewai,langchain,llamaindex,mcp,ml,postgres,redis]; extra == "all"
45
56
  Dynamic: license-file
46
57
 
47
58
  # 🛡️ HumaneProxy
@@ -56,8 +67,8 @@ HumaneProxy sits between your users and any LLM. When someone expresses self-har
56
67
  [![Python](https://img.shields.io/pypi/pyversions/humane-proxy.svg)](https://pypi.org/project/humane-proxy/)
57
68
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
58
69
  [![Tests](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml/badge.svg)](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml)
59
- [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/card.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
60
70
  [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/score.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
71
+ [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/card.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
61
72
 
62
73
  ---
63
74
 
@@ -175,6 +186,8 @@ stage2:
175
186
  safe_threshold: 0.35 # cosine similarity below this → safe
176
187
  ```
177
188
 
189
+ > **Multilingual Support:** If your users converse in non-English languages (Roman Hindi, Spanish, Arabic, etc.), change the `model` in your configuration to `"paraphrase-multilingual-MiniLM-L12-v2"`. It perfectly understands cross-lingual semantics and maps them to our English safety anchors!
190
+
178
191
  The model lazy-loads on first use. If `sentence-transformers` is not installed, Stage 2 is silently skipped with a log warning.
179
192
 
180
193
  > **How Stage 2 works with Stage 1:** When you enable `[1, 2]`, **every message** that Stage 1 does not flag as definitive `self_harm` proceeds to the embedding classifier. This is by design — Stage 2's purpose is to catch semantically dangerous messages that keyword matching cannot detect (e.g. *"Nobody would notice if I disappeared"*). Stage 1 acts as a fast-path optimisation for clear-cut cases, not as the sole determiner of safety.
@@ -234,6 +247,10 @@ HumaneProxy returns an empathetic message with crisis resources for 10+ countrie
234
247
  safety:
235
248
  categories:
236
249
  self_harm:
250
+ # Self-harm escalation threshold (0.0 to 1.0).
251
+ # Scores below this are downgraded to safe.
252
+ escalate_threshold: 0.5
253
+
237
254
  response_mode: "block" # default
238
255
 
239
256
  # Optional: override the built-in message
@@ -258,6 +275,67 @@ The injected system prompt instructs the LLM to respond with empathy, validate f
258
275
 
259
276
  ---
260
277
 
278
+ ## Risk Trajectory & Time-Decay
279
+
280
+ HumaneProxy tracks a **rolling window** of the last 5 risk scores per session.
281
+ When a new message arrives, its score is compared against the
282
+ **decay-weighted mean** of that window:
283
+
284
+ ```
285
+ delta = current_score − weighted_mean(last N scores)
286
+ spike = delta > 0.35 (configurable via spike_delta)
287
+ ```
288
+
289
+ If a spike is detected, a **boost penalty** (`+0.25`) is added to the
290
+ current score to push it closer to escalation.
291
+
292
+ ### Exponential Time-Decay
293
+
294
+ Historical scores are weighted using the formula:
295
+
296
+ $$w_i = e^{-\lambda \, \Delta t_i}$$
297
+
298
+ where **λ = ln(2) / half-life** and **Δt** is the age of each score in
299
+ seconds. This means:
300
+
301
+ | Time elapsed | Weight (24 h half-life) | Meaning |
302
+ |---|---|---|
303
+ | 5 minutes | 99.8 % | Near-full weight — live conversation |
304
+ | 6 hours | 84 % | Still highly relevant |
305
+ | 24 hours | 50 % | Half weight — yesterday's scores |
306
+ | 48 hours | 25 % | Faded — two days ago |
307
+ | 72 hours | 12.5 % | Nearly forgotten |
308
+
309
+ **Why this matters:** Without decay, a user who had a tough conversation
310
+ on Monday would carry that elevated baseline into Thursday—unfairly
311
+ triggering spikes on innocuous messages. With a 24-hour half-life,
312
+ old scores gracefully fade while rapid within-session escalation is
313
+ still caught instantly.
314
+
315
+ ### Configuration
316
+
317
+ ```yaml
318
+ trajectory:
319
+ window_size: 5 # messages in rolling window
320
+ spike_delta: 0.35 # delta threshold for spike detection
321
+
322
+ # Half-life in hours. After this period, a historical score
323
+ # carries only 50 % of its original weight.
324
+ # 24 → balanced forgiveness + familiarity (default)
325
+ # 6 → aggressive decay, only very recent history matters
326
+ # 72 → gentle decay, multi-day memory
327
+ # 0 → disable decay (plain unweighted mean)
328
+ decay_half_life_hours: 24.0
329
+ ```
330
+
331
+ Or via environment variable:
332
+
333
+ ```bash
334
+ export HUMANE_PROXY_DECAY_HALF_LIFE=12 # 12-hour half-life
335
+ ```
336
+
337
+ ---
338
+
261
339
  ## Alert Webhooks
262
340
 
263
341
  Configure in `humane_proxy.yaml`:
@@ -284,6 +362,10 @@ escalation:
284
362
  to:
285
363
  - "safety-team@yourorg.com"
286
364
  - "oncall@yourorg.com"
365
+
366
+ # Swappable Storage Backend (sqlite config default, redis/postgres optional)
367
+ storage:
368
+ backend: "sqlite" # or "redis", "postgres"
287
369
  ```
288
370
 
289
371
  ---
@@ -333,10 +415,13 @@ curl -X DELETE http://localhost:8000/admin/sessions/user-42 \
333
415
 
334
416
  | Endpoint | Description |
335
417
  |---|---|
336
- | `GET /admin/escalations` | Paginated list, filterable by `category`, `session_id` |
418
+ | `GET /admin/health` | Health check (no auth required) |
419
+ | `GET /admin/config` | Active config view (secrets redacted) |
420
+ | `GET /admin/escalations` | Paginated list, filterable by `category`, `session_id`, `date`, sortable |
421
+ | `GET /admin/escalations/export` | CSV export of escalations |
337
422
  | `GET /admin/escalations/{id}` | Single escalation detail |
338
423
  | `GET /admin/sessions/{id}/risk` | Session history + trajectory |
339
- | `GET /admin/stats` | Aggregate counts by category and day |
424
+ | `GET /admin/stats` | Aggregate counts, top sessions, hourly breakdown |
340
425
  | `DELETE /admin/sessions/{id}` | Delete all session records |
341
426
 
342
427
  ---
@@ -361,10 +446,38 @@ Available on the [Official MCP Registry](https://registry.modelcontextprotocol.i
361
446
 
362
447
  ---
363
448
 
364
- ## LangChain Integration
449
+ ## AI Agent Integrations
365
450
 
366
- Plug HumaneProxy safety tools into any LangChain or LangGraph agent:
451
+ HumaneProxy tools can be natively plugged into standard agentic frameworks:
452
+
453
+ ### LlamaIndex
454
+ ```bash
455
+ pip install humane-proxy[llamaindex]
456
+ ```
457
+ ```python
458
+ from humane_proxy.integrations.llamaindex import get_safety_tools
459
+ tools = get_safety_tools() # Native FunctionTool instances
460
+ ```
461
+
462
+ ### CrewAI
463
+ ```bash
464
+ pip install humane-proxy[crewai]
465
+ ```
466
+ ```python
467
+ from humane_proxy.integrations.crewai import get_safety_tools
468
+ tools = get_safety_tools() # Native BaseTool subclass instances
469
+ ```
470
+
471
+ ### AutoGen (AG2)
472
+ ```bash
473
+ pip install humane-proxy[autogen]
474
+ ```
475
+ ```python
476
+ from humane_proxy.integrations.autogen import register_safety_tools
477
+ register_safety_tools(assistant, user_proxy)
478
+ ```
367
479
 
480
+ ### LangChain
368
481
  ```bash
369
482
  pip install humane-proxy[langchain]
370
483
  ```
@@ -390,15 +503,17 @@ All values can be set in `humane_proxy.yaml` (project root) or via `HUMANE_PROXY
390
503
  | YAML key | Env var | Default | Description |
391
504
  |---|---|---|---|
392
505
  | `safety.risk_threshold` | `HUMANE_PROXY_RISK_THRESHOLD` | `0.7` | Score threshold for criminal_intent escalation |
393
- | `safety.spike_boost` | | `0.25` | Score boost on trajectory spike |
506
+ | `safety.categories.self_harm.escalate_threshold` | `HUMANE_PROXY_SELF_HARM_THRESHOLD` | `0.5` | Score threshold for self_harm escalation |
507
+ | `safety.spike_boost` | `HUMANE_PROXY_SPIKE_BOOST` | `0.25` | Score boost on trajectory spike |
394
508
  | `server.port` | `HUMANE_PROXY_PORT` | `8000` | Proxy port |
395
- | `pipeline.enabled_stages` | `HUMANE_PROXY_ENABLED_STAGES` | `[1]` | Active stages |
509
+ | `pipeline.enabled_stages` | `HUMANE_PROXY_ENABLED_STAGES` | `[1]` | Active stages (e.g. `1,2,3`) |
396
510
  | `pipeline.stage1_ceiling` | `HUMANE_PROXY_STAGE1_CEILING` | `0.3` | Early exit after Stage 1 |
397
511
  | `pipeline.stage2_ceiling` | `HUMANE_PROXY_STAGE2_CEILING` | `0.4` | Early exit after Stage 2 |
398
512
  | `stage3.provider` | `HUMANE_PROXY_STAGE3_PROVIDER` | `"auto"` | Stage 3 provider |
399
513
  | `stage3.timeout` | `HUMANE_PROXY_STAGE3_TIMEOUT` | `10` | Stage 3 timeout (s) |
400
514
  | `privacy.store_message_text` | — | `false` | Store raw text (vs SHA-256 hash) |
401
- | `escalation.rate_limit_max` | | `3` | Max alerts per session/window |
515
+ | `escalation.rate_limit_max` | `HUMANE_PROXY_RATE_LIMIT_MAX` | `3` | Max alerts per session/window |
516
+ | `storage.backend` | `HUMANE_PROXY_STORAGE_BACKEND` | `"sqlite"` | `"sqlite"`, `"redis"`, `"postgres"` |
402
517
  | `safety.categories.self_harm.response_mode` | — | `"block"` | `"block"` or `"forward"` |
403
518
 
404
519
  ---
@@ -428,11 +543,16 @@ privacy:
428
543
 
429
544
  | Extra | Command | What it adds |
430
545
  |---|---|---|
431
- | *(none)* | `pip install humane-proxy` | Stage 1 heuristics + full API + CLI |
546
+ | *(none)* | `pip install humane-proxy` | Stage 1 heuristics + default SQLite storage |
432
547
  | `ml` | `pip install humane-proxy[ml]` | Stage 2 semantic embeddings (`sentence-transformers`) |
433
548
  | `mcp` | `pip install humane-proxy[mcp]` | MCP server for AI agent integration (`fastmcp`) |
549
+ | `redis` | `pip install humane-proxy[redis]` | Redis storage backend (`redis`) |
550
+ | `postgres` | `pip install humane-proxy[postgres]` | PostgreSQL storage backend (`psycopg`, `psycopg_pool`) |
551
+ | `llamaindex` | `pip install humane-proxy[llamaindex]` | LlamaIndex native integration (`llama-index-core`) |
552
+ | `crewai` | `pip install humane-proxy[crewai]` | CrewAI native integration (`crewai[tools]`) |
553
+ | `autogen` | `pip install humane-proxy[autogen]` | AutoGen native integration (`autogen-agentchat`) |
434
554
  | `langchain` | `pip install humane-proxy[langchain]` | LangChain adapter (MCP + `langchain-mcp-adapters`) |
435
- | `all` | `pip install humane-proxy[all]` | Everything above |
555
+ | `all` | `pip install humane-proxy[all]` | Includes ALL optional dependencies above |
436
556
 
437
557
  ---
438
558
 
@@ -10,8 +10,8 @@ HumaneProxy sits between your users and any LLM. When someone expresses self-har
10
10
  [![Python](https://img.shields.io/pypi/pyversions/humane-proxy.svg)](https://pypi.org/project/humane-proxy/)
11
11
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
12
12
  [![Tests](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml/badge.svg)](https://github.com/Vishisht16/Humane-Proxy/actions/workflows/tests.yaml)
13
- [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/card.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
14
13
  [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/score.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
14
+ [![Humane-Proxy MCP server](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy/badges/card.svg)](https://glama.ai/mcp/servers/Vishisht16/Humane-Proxy)
15
15
 
16
16
  ---
17
17
 
@@ -129,6 +129,8 @@ stage2:
129
129
  safe_threshold: 0.35 # cosine similarity below this → safe
130
130
  ```
131
131
 
132
+ > **Multilingual Support:** If your users converse in non-English languages (Roman Hindi, Spanish, Arabic, etc.), change the `model` in your configuration to `"paraphrase-multilingual-MiniLM-L12-v2"`. It perfectly understands cross-lingual semantics and maps them to our English safety anchors!
133
+
132
134
  The model lazy-loads on first use. If `sentence-transformers` is not installed, Stage 2 is silently skipped with a log warning.
133
135
 
134
136
  > **How Stage 2 works with Stage 1:** When you enable `[1, 2]`, **every message** that Stage 1 does not flag as definitive `self_harm` proceeds to the embedding classifier. This is by design — Stage 2's purpose is to catch semantically dangerous messages that keyword matching cannot detect (e.g. *"Nobody would notice if I disappeared"*). Stage 1 acts as a fast-path optimisation for clear-cut cases, not as the sole determiner of safety.
@@ -188,6 +190,10 @@ HumaneProxy returns an empathetic message with crisis resources for 10+ countrie
188
190
  safety:
189
191
  categories:
190
192
  self_harm:
193
+ # Self-harm escalation threshold (0.0 to 1.0).
194
+ # Scores below this are downgraded to safe.
195
+ escalate_threshold: 0.5
196
+
191
197
  response_mode: "block" # default
192
198
 
193
199
  # Optional: override the built-in message
@@ -212,6 +218,67 @@ The injected system prompt instructs the LLM to respond with empathy, validate f
212
218
 
213
219
  ---
214
220
 
221
+ ## Risk Trajectory & Time-Decay
222
+
223
+ HumaneProxy tracks a **rolling window** of the last 5 risk scores per session.
224
+ When a new message arrives, its score is compared against the
225
+ **decay-weighted mean** of that window:
226
+
227
+ ```
228
+ delta = current_score − weighted_mean(last N scores)
229
+ spike = delta > 0.35 (configurable via spike_delta)
230
+ ```
231
+
232
+ If a spike is detected, a **boost penalty** (`+0.25`) is added to the
233
+ current score to push it closer to escalation.
234
+
235
+ ### Exponential Time-Decay
236
+
237
+ Historical scores are weighted using the formula:
238
+
239
+ $$w_i = e^{-\lambda \, \Delta t_i}$$
240
+
241
+ where **λ = ln(2) / half-life** and **Δt** is the age of each score in
242
+ seconds. This means:
243
+
244
+ | Time elapsed | Weight (24 h half-life) | Meaning |
245
+ |---|---|---|
246
+ | 5 minutes | 99.8 % | Near-full weight — live conversation |
247
+ | 6 hours | 84 % | Still highly relevant |
248
+ | 24 hours | 50 % | Half weight — yesterday's scores |
249
+ | 48 hours | 25 % | Faded — two days ago |
250
+ | 72 hours | 12.5 % | Nearly forgotten |
251
+
252
+ **Why this matters:** Without decay, a user who had a tough conversation
253
+ on Monday would carry that elevated baseline into Thursday—unfairly
254
+ triggering spikes on innocuous messages. With a 24-hour half-life,
255
+ old scores gracefully fade while rapid within-session escalation is
256
+ still caught instantly.
257
+
258
+ ### Configuration
259
+
260
+ ```yaml
261
+ trajectory:
262
+ window_size: 5 # messages in rolling window
263
+ spike_delta: 0.35 # delta threshold for spike detection
264
+
265
+ # Half-life in hours. After this period, a historical score
266
+ # carries only 50 % of its original weight.
267
+ # 24 → balanced forgiveness + familiarity (default)
268
+ # 6 → aggressive decay, only very recent history matters
269
+ # 72 → gentle decay, multi-day memory
270
+ # 0 → disable decay (plain unweighted mean)
271
+ decay_half_life_hours: 24.0
272
+ ```
273
+
274
+ Or via environment variable:
275
+
276
+ ```bash
277
+ export HUMANE_PROXY_DECAY_HALF_LIFE=12 # 12-hour half-life
278
+ ```
279
+
280
+ ---
281
+
215
282
  ## Alert Webhooks
216
283
 
217
284
  Configure in `humane_proxy.yaml`:
@@ -238,6 +305,10 @@ escalation:
238
305
  to:
239
306
  - "safety-team@yourorg.com"
240
307
  - "oncall@yourorg.com"
308
+
309
+ # Swappable Storage Backend (sqlite config default, redis/postgres optional)
310
+ storage:
311
+ backend: "sqlite" # or "redis", "postgres"
241
312
  ```
242
313
 
243
314
  ---
@@ -287,10 +358,13 @@ curl -X DELETE http://localhost:8000/admin/sessions/user-42 \
287
358
 
288
359
  | Endpoint | Description |
289
360
  |---|---|
290
- | `GET /admin/escalations` | Paginated list, filterable by `category`, `session_id` |
361
+ | `GET /admin/health` | Health check (no auth required) |
362
+ | `GET /admin/config` | Active config view (secrets redacted) |
363
+ | `GET /admin/escalations` | Paginated list, filterable by `category`, `session_id`, `date`, sortable |
364
+ | `GET /admin/escalations/export` | CSV export of escalations |
291
365
  | `GET /admin/escalations/{id}` | Single escalation detail |
292
366
  | `GET /admin/sessions/{id}/risk` | Session history + trajectory |
293
- | `GET /admin/stats` | Aggregate counts by category and day |
367
+ | `GET /admin/stats` | Aggregate counts, top sessions, hourly breakdown |
294
368
  | `DELETE /admin/sessions/{id}` | Delete all session records |
295
369
 
296
370
  ---
@@ -315,10 +389,38 @@ Available on the [Official MCP Registry](https://registry.modelcontextprotocol.i
315
389
 
316
390
  ---
317
391
 
318
- ## LangChain Integration
392
+ ## AI Agent Integrations
319
393
 
320
- Plug HumaneProxy safety tools into any LangChain or LangGraph agent:
394
+ HumaneProxy tools can be natively plugged into standard agentic frameworks:
395
+
396
+ ### LlamaIndex
397
+ ```bash
398
+ pip install humane-proxy[llamaindex]
399
+ ```
400
+ ```python
401
+ from humane_proxy.integrations.llamaindex import get_safety_tools
402
+ tools = get_safety_tools() # Native FunctionTool instances
403
+ ```
404
+
405
+ ### CrewAI
406
+ ```bash
407
+ pip install humane-proxy[crewai]
408
+ ```
409
+ ```python
410
+ from humane_proxy.integrations.crewai import get_safety_tools
411
+ tools = get_safety_tools() # Native BaseTool subclass instances
412
+ ```
413
+
414
+ ### AutoGen (AG2)
415
+ ```bash
416
+ pip install humane-proxy[autogen]
417
+ ```
418
+ ```python
419
+ from humane_proxy.integrations.autogen import register_safety_tools
420
+ register_safety_tools(assistant, user_proxy)
421
+ ```
321
422
 
423
+ ### LangChain
322
424
  ```bash
323
425
  pip install humane-proxy[langchain]
324
426
  ```
@@ -344,15 +446,17 @@ All values can be set in `humane_proxy.yaml` (project root) or via `HUMANE_PROXY
344
446
  | YAML key | Env var | Default | Description |
345
447
  |---|---|---|---|
346
448
  | `safety.risk_threshold` | `HUMANE_PROXY_RISK_THRESHOLD` | `0.7` | Score threshold for criminal_intent escalation |
347
- | `safety.spike_boost` | | `0.25` | Score boost on trajectory spike |
449
+ | `safety.categories.self_harm.escalate_threshold` | `HUMANE_PROXY_SELF_HARM_THRESHOLD` | `0.5` | Score threshold for self_harm escalation |
450
+ | `safety.spike_boost` | `HUMANE_PROXY_SPIKE_BOOST` | `0.25` | Score boost on trajectory spike |
348
451
  | `server.port` | `HUMANE_PROXY_PORT` | `8000` | Proxy port |
349
- | `pipeline.enabled_stages` | `HUMANE_PROXY_ENABLED_STAGES` | `[1]` | Active stages |
452
+ | `pipeline.enabled_stages` | `HUMANE_PROXY_ENABLED_STAGES` | `[1]` | Active stages (e.g. `1,2,3`) |
350
453
  | `pipeline.stage1_ceiling` | `HUMANE_PROXY_STAGE1_CEILING` | `0.3` | Early exit after Stage 1 |
351
454
  | `pipeline.stage2_ceiling` | `HUMANE_PROXY_STAGE2_CEILING` | `0.4` | Early exit after Stage 2 |
352
455
  | `stage3.provider` | `HUMANE_PROXY_STAGE3_PROVIDER` | `"auto"` | Stage 3 provider |
353
456
  | `stage3.timeout` | `HUMANE_PROXY_STAGE3_TIMEOUT` | `10` | Stage 3 timeout (s) |
354
457
  | `privacy.store_message_text` | — | `false` | Store raw text (vs SHA-256 hash) |
355
- | `escalation.rate_limit_max` | | `3` | Max alerts per session/window |
458
+ | `escalation.rate_limit_max` | `HUMANE_PROXY_RATE_LIMIT_MAX` | `3` | Max alerts per session/window |
459
+ | `storage.backend` | `HUMANE_PROXY_STORAGE_BACKEND` | `"sqlite"` | `"sqlite"`, `"redis"`, `"postgres"` |
356
460
  | `safety.categories.self_harm.response_mode` | — | `"block"` | `"block"` or `"forward"` |
357
461
 
358
462
  ---
@@ -382,11 +486,16 @@ privacy:
382
486
 
383
487
  | Extra | Command | What it adds |
384
488
  |---|---|---|
385
- | *(none)* | `pip install humane-proxy` | Stage 1 heuristics + full API + CLI |
489
+ | *(none)* | `pip install humane-proxy` | Stage 1 heuristics + default SQLite storage |
386
490
  | `ml` | `pip install humane-proxy[ml]` | Stage 2 semantic embeddings (`sentence-transformers`) |
387
491
  | `mcp` | `pip install humane-proxy[mcp]` | MCP server for AI agent integration (`fastmcp`) |
492
+ | `redis` | `pip install humane-proxy[redis]` | Redis storage backend (`redis`) |
493
+ | `postgres` | `pip install humane-proxy[postgres]` | PostgreSQL storage backend (`psycopg`, `psycopg_pool`) |
494
+ | `llamaindex` | `pip install humane-proxy[llamaindex]` | LlamaIndex native integration (`llama-index-core`) |
495
+ | `crewai` | `pip install humane-proxy[crewai]` | CrewAI native integration (`crewai[tools]`) |
496
+ | `autogen` | `pip install humane-proxy[autogen]` | AutoGen native integration (`autogen-agentchat`) |
388
497
  | `langchain` | `pip install humane-proxy[langchain]` | LangChain adapter (MCP + `langchain-mcp-adapters`) |
389
- | `all` | `pip install humane-proxy[all]` | Everything above |
498
+ | `all` | `pip install humane-proxy[all]` | Includes ALL optional dependencies above |
390
499
 
391
500
  ---
392
501
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- __version__ = "0.2.3"
19
+ __version__ = "0.3.1"
20
20
 
21
21
  # ---------------------------------------------------------------------------
22
22
  # Legacy API — keep backward compatibility with existing modules that call