Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.
Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles
Excluded from snapshot: venv/, .env, data/, backups, .tgz archives
Co-authored-by: Cursor <cursoragent@cursor.com>
213 lines
6.9 KiB
Markdown
213 lines
6.9 KiB
Markdown
# Runbook: Behavior Policy v2.1
|
|
|
|
**Version:** 2.1
|
|
**Date:** 2026-02-07
|
|
**Owner:** NODA1 Infra
|
|
**Severity:** CRITICAL (affects all agent responses)
|
|
|
|
---
|
|
|
|
## 1. File Locations
|
|
|
|
| File | Path | Purpose |
|
|
|------|------|---------|
|
|
| Behavior Policy | `gateway-bot/behavior_policy.py` | SOWA decision logic |
|
|
| HTTP API (gateway) | `gateway-bot/http_api.py` | Webhook handler, computes gateway metadata |
|
|
| Global System Prompt | `prompts/global_system_prompt_v2.md` | Policy document for LLM |
|
|
| Tests | `tests/test_behavior_policy.py` | 39 unit tests |
|
|
| Backup (policy) | `gateway-bot/behavior_policy.py.bak.*` | Timestamped backups |
|
|
| Backup (http_api) | `gateway-bot/http_api.py.bak.*` | Timestamped backups |
|
|
| Old policy (v1) | `gateway-bot/behavior_policy_v1.txt` | Reference only |
|
|
|
|
---
|
|
|
|
## 2. Quick Disable / Rollback
|
|
|
|
### Option A: Rollback to backup (fastest, ~10s)
|
|
|
|
```bash
|
|
cd /opt/microdao-daarion
|
|
|
|
# List backups
|
|
ls -lt gateway-bot/behavior_policy.py.bak.*
|
|
ls -lt gateway-bot/http_api.py.bak.*
|
|
|
|
# Rollback
|
|
cp gateway-bot/behavior_policy.py.bak.20260207_085440 gateway-bot/behavior_policy.py
|
|
cp gateway-bot/http_api.py.bak.20260207_085440 gateway-bot/http_api.py
|
|
|
|
# Restart gateway
|
|
docker compose -f docker-compose.node1.yml restart gateway
|
|
```
|
|
|
|
### Option B: Feature flag via ENV (no restart needed for next deploy)
|
|
|
|
Add to `.env`:
|
|
|
|
```
|
|
BEHAVIOR_POLICY_VERSION=v1.1
|
|
```
|
|
|
|
Then in `http_api.py`, wrap v2.1 logic:
|
|
|
|
```python
|
|
if os.getenv("BEHAVIOR_POLICY_VERSION", "v2.1") == "v1.1":
|
|
# Old behavior: bare mention responds
|
|
payload_explicit_request = False
|
|
# ... old call
|
|
```
|
|
|
|
> **Note:** Option B requires code change. Option A is preferred for emergency.
|
|
|
|
### Option C: Disable SOWA entirely (all agents respond to everything)
|
|
|
|
```bash
|
|
# In http_api.py, force respond_decision = True
|
|
# NOT RECOMMENDED for production — causes spam
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Run Unit Tests
|
|
|
|
```bash
|
|
cd /opt/microdao-daarion
|
|
python3 -m pytest tests/test_behavior_policy.py -v
|
|
```
|
|
|
|
Expected: `39 passed`
|
|
|
|
If pytest not installed:
|
|
|
|
```bash
|
|
pip3 install --break-system-packages pytest
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Run Live Tests (7 scenarios)
|
|
|
|
All tests use `chat_id=0` (prober mode — no Telegram messages sent).
|
|
|
|
```bash
|
|
# Test 1: Bare mention in group → should NOT respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999001,"message":{"message_id":1001,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"@Helion","date":1738900000}}'
|
|
# Expected: {"ok":true,"skipped":true,"reason":"bare_mention_public_topic"}
|
|
|
|
# Test 2: Mention + question → should respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999002,"message":{"message_id":1002,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"supergroup","title":"TestGroup"},"text":"@Helion що таке Docker?","date":1738900001}}'
|
|
# Expected: {"ok":true,"agent":"helion","prober":true,...}
|
|
|
|
# Test 3: DM → always respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999003,"message":{"message_id":1003,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"private"},"text":"Привіт","date":1738900002}}'
|
|
# Expected: {"ok":true,"agent":"helion","prober":true,...}
|
|
|
|
# Test 4: Broadcast → should NOT respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999004,"message":{"message_id":1004,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"увага всім! релізимо v2.0","date":1738900003}}'
|
|
# Expected: {"ok":true,"skipped":true,"reason":"broadcast_not_directed"}
|
|
|
|
# Test 5: Link only → should NOT respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999005,"message":{"message_id":1005,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"https://github.com/project/pull/123","date":1738900004}}'
|
|
# Expected: {"ok":true,"skipped":true,"reason":"media_or_link_without_request"}
|
|
|
|
# Test 6: Question without mention → should NOT respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999006,"message":{"message_id":1006,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"Хто знає чому падає сервер?","date":1738900005}}'
|
|
# Expected: {"ok":true,"skipped":true,"reason":"not_directed_to_agent"}
|
|
|
|
# Test 7: Mention + imperative → should respond
|
|
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"update_id":999007,"message":{"message_id":1007,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"supergroup","title":"TestGroup"},"text":"@Helion поясни що таке SOWA","date":1738900006}}'
|
|
# Expected: {"ok":true,"agent":"helion","prober":true,...}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Verify After Restart
|
|
|
|
```bash
|
|
# 1. Restart gateway
|
|
docker compose -f docker-compose.node1.yml restart gateway
|
|
|
|
# 2. Wait 10s
|
|
sleep 10
|
|
|
|
# 3. Check health
|
|
curl -s http://localhost:9300/health | python3 -m json.tool
|
|
|
|
# 4. Check all agents loaded
|
|
# Expected: 10 agents, all prompt_loaded=true
|
|
|
|
# 5. Run agent ping
|
|
curl -s -X POST http://localhost:9300/debug/agent_ping | python3 -m json.tool
|
|
|
|
# 6. Check logs for errors
|
|
docker logs dagi-gateway-node1 --tail 20
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Monitor Policy Violations
|
|
|
|
Check for `policy_violation` in logs:
|
|
|
|
```bash
|
|
# Real-time monitoring
|
|
docker logs -f dagi-gateway-node1 2>&1 | grep 'policy_violation'
|
|
|
|
# Last 1000 lines
|
|
docker logs dagi-gateway-node1 --tail 1000 2>&1 | grep 'policy_violation'
|
|
|
|
# Count violations per agent
|
|
docker logs dagi-gateway-node1 --tail 5000 2>&1 | grep 'policy_violation' | grep -oP 'agent=\w+' | sort | uniq -c | sort -rn
|
|
```
|
|
|
|
Log format:
|
|
```
|
|
🚨 policy_violation=no_output_extra_text agent=helion chat_id=-100123 extra_text_len=45 extra_preview='Some unexpected text...'
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Key Contracts (Do Not Break)
|
|
|
|
### has_explicit_request formula
|
|
```
|
|
has_explicit_request = imperative
|
|
OR (question_mark AND (is_dm OR is_reply_to_agent OR mentioned_agents not empty OR thread_has_agent_participation))
|
|
```
|
|
|
|
### thread_has_agent_participation
|
|
- REQUIRED field
|
|
- If platform cannot provide → `false` (fail-closed)
|
|
- Gateway MUST always pass, even as `false`
|
|
|
|
### NO_OUTPUT contract
|
|
- LLM must return exactly `NO_OUTPUT` or empty string
|
|
- Any extra text after marker → logged as `policy_violation=no_output_extra_text`
|
|
- Gateway suppresses sending to Telegram
|
|
|
|
---
|
|
|
|
## 8. Contacts
|
|
|
|
- **NODA1 Admin:** @DaarionAdmin
|
|
- **Infra:** SSH root@144.76.224.179
|
|
- **Monitoring:** Grafana :3030 / Prometheus :9090
|
|
|
|
---
|
|
|
|
**END OF RUNBOOK**
|