---
type: skill
domain: architecture
links: [Corpus_Callosum/CONSTITUTION.md, PULSE_OS.md]
---

# NETWORK_NOMAD
> **ROLE:** CONNECTIVITY ARCHITECT
> **TRIGGER:** "API CALL"

## Core Mandate
The network is unreliable. The code must not be. Every external call gets a timeout, a retry, and a fallback.

## Step-by-Step Protocol
1. **Brain check**: `python pulse/brain/brain_query.py --query "network patterns for <API/service>"`
2. **Wrap every external call** in retry logic with exponential backoff: `delay = min(2^attempt * 100ms, 30s)`, max 5 retries.
3. **Set explicit timeouts** on all requests: connect=5s, read=30s. Never use `timeout=None`.
4. **Implement circuit breaker**: After 3 consecutive failures, stop calling for 60 seconds. Log the circuit-open event.
5. **Verify TLS and sanitize headers**: No plaintext HTTP. Strip `Server`, `X-Powered-By` from responses.

## Exponential Backoff Formula
```
delay = min(2^attempt * 100ms, max_delay)
```
| Attempt | Delay | Cumulative |
|---|---|---|
| 1 | 200ms | 200ms |
| 2 | 400ms | 600ms |
| 3 | 800ms | 1.4s |
| 4 | 1600ms | 3.0s |
| 5 | 3200ms | 6.2s |

Add jitter: `delay = delay * (0.5 + random.random() * 0.5)` to prevent thundering herd.

## Good Example
```python
import time, random, requests

def resilient_call(url: str, max_retries: int = 5) -> requests.Response:
    for attempt in range(max_retries):
        try:
            resp = requests.get(url, timeout=(5, 30))
            resp.raise_for_status()
            return resp
        except requests.RequestException:
            if attempt == max_retries - 1:
                raise
            delay = min(2 ** attempt * 0.1, 30)
            delay *= 0.5 + random.random() * 0.5  # jitter
            time.sleep(delay)
```

## Metrics & Thresholds
| Metric | Threshold |
|---|---|
| Connect timeout | 5 seconds max |
| Read timeout | 30 seconds max |
| Max retries | 5 attempts |
| Circuit breaker trigger | 3 consecutive failures |
| Circuit breaker cooldown | 60 seconds |
| Max backoff cap | 30 seconds |

## Anti-Patterns
- **`timeout=None`**: Hangs forever if server is down. Always set both connect and read timeouts.
- **Retry without backoff**: Hammering a failing server makes it worse. Always use exponential delay.
- **Catching `requests.RequestException` and returning `None`**: Caller won't know the call failed. Raise or return a result object with error info.

## Tools to Use
- `brain_query.py --query "API retry patterns"` -- check brain for prior network lessons
- `pulse_relay.py --tasks "Add retry logic:architecture:fast"` -- delegate to agents
- `pulse_save.py --learnings "..." --failures "..."` -- record network incidents

## Verification Checklist
- [ ] Every `requests.get/post` call has explicit `timeout=(connect, read)`
- [ ] Retry logic uses exponential backoff with jitter
- [ ] Circuit breaker implemented for repeated-failure APIs
- [ ] No plaintext HTTP URLs (all HTTPS)
- [ ] No `timeout=None` anywhere in codebase
- [ ] Rate limiting respected (check `Retry-After` header)
