Home
Overview

Introduction

Nozie is a lightweight Python monitoring probe that watches your Docker containers, detects runtime errors, and reports them to the Nozie backend — where Nozie analyzes root causes and opens an auto-fix GitHub pull request.

The library runs entirely in background daemon threads and never blocks your application. No AI keys or GitHub tokens are required on your server — all intelligence happens in the Nozie cloud backend.

Lightweight probe
Runs in daemon threads. Zero impact on your app's main process. Uses Docker SDK for real-time log streaming.
Zero secrets on server
No API key or GitHub token needed on your machine. Everything is handled by the Nozie backend.
Auto-fix PRs
When an error is detected, the backend uses Nozie to diagnose and patch the code, then opens a PR on your behalf.
Real-time stats
Heartbeat reports of CPU, memory, and restart counts every 30 seconds. Viewable in your Nozie dashboard.

Requirements

  • Python ≥ 3.8
  • Docker daemon running on the same host
  • A Nozie API key — get one from your dashboard
  • Your GitHub repo connected in the dashboard (for auto-fix PRs)
Overview

How It Works

From container crash to a merged GitHub pull request — Nozie closes the loop automatically while you sleep.

01
Detect
NozieAgent connects to the Docker socket and streams logs in real time from your containers. It also watches Docker events (die, stop, kill, oom) for instant status reporting without waiting for the next stats cycle.
02
Buffer & match
Each log line is appended to a 50-line rolling buffer. When the agent sees a pattern matching ERROR, Exception, Traceback, or FATAL, it captures the buffer as context for analysis.
03
Report to backend
The agent POSTs the log snippet to the Nozie backend API with your API key as authentication. A cooldown prevents flooding — the same container can only send one error report per 60 seconds by default.
04
AI analysis & PR
The backend passes the log context and your repository source code to Nozie. It identifies the root cause, generates a minimal patch, and opens a GitHub pull request with a detailed explanation.

Thread Architecture

Nozie spawns a ThreadPoolExecutor with up to 5 worker threads:

  • nozie-main — orchestrates the agent startup and keeps the process alive
  • stats loop — sends heartbeat stats every stats_interval seconds
  • events loop — watches Docker events for instant status changes
  • log monitor (per container) — one thread per monitored container
Daemon threads — all Nozie threads are daemon threads, so they exit automatically when your main process ends. You never need to call stop() for clean shutdown.
Getting Started

Installation

Install the Nozie library from PyPI using pip. It requires Python 3.8 or newer and an active Docker daemon on the same host.

Install via pip

bash
pip install nozie

Dependencies

Nozie automatically installs these packages as dependencies:

PackageVersionPurpose
docker≥ 7.0.0Docker SDK for Python — connects to the Docker socket
pydantic≥ 2.0.0Configuration validation and type safety
requests≥ 2.31.0HTTP client for reporting to the Nozie backend

Optional extras

If you are self-hosting the Nozie backend and want to use the built-in AI analysis or GitHub integration on your own server, install the backend extras:

bash
pip install nozie[backend]

This adds two optional packages not required by the probe itself:

PackagePurpose
anthropic ≥ 0.25.0Anthropic Python SDK for AI-powered error analysis
PyGithub ≥ 2.0.0GitHub API client for opening auto-fix pull requests
The standard pip install nozie is all you need to run the monitoring probe on your server. The [backend] extra is only needed when you run the Nozie analysis server itself.

Verify installation

python
import nozie
print("nozie ready")

Docker requirement

Nozie connects to Docker via docker.from_env(), which reads the DOCKER_HOST environment variable or falls back to the local socket at /var/run/docker.sock.

Linux / macOS: Docker Desktop and Docker Engine both expose the socket at /var/run/docker.sock by default.

Windows: Docker Desktop exposes the named pipe npipe:////./pipe/docker_engine. The Python Docker SDK detects this automatically.
Getting Started

Quickstart

Two lines of code are all you need to start monitoring. Get your API key from the dashboard, then add the agent to your project.

Minimal setup

Start monitoring all running containers:

python
import time
from nozie import NozieAgent

NozieAgent(api_key="nz_k_your_key_here").start()

# .start() is non-blocking — keep the process alive, or the daemon
# threads it spawned die with it the instant the script reaches the end.
while True:
    time.sleep(1)
Run this as its own file and its own container — never inside the app you're watching. Nozie watches a container from the outside and has to be able to restart or rebuild it when a fix merges. A copy of the agent living inside the same process as the app it's watching can't do either job: if the app crashes for real, the in-process agent dies with it and nobody is left to report it, and a process can't restart the very container it's running inside of — the restart signal kills it first. Put the snippet above in its own file (e.g. agent_runner.py) and run it as a separate service in your docker-compose.yml, with /var/run/docker.sock mounted into that service only — not the app's own container, as shown below.
yaml
# docker-compose.yml
services:
  your-app:
    # ... your existing app service, unchanged ...

  nozie-agent:
    image: python:3.11-slim
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./agent_runner.py:/agent_runner.py
    working_dir: /
    command: sh -c "pip install nozie && python agent_runner.py"
    environment:
      - NOZIE_API_KEY=${NOZIE_API_KEY}
    depends_on:
      - your-app

Monitor a specific container

python
from nozie import NozieAgent

agent = NozieAgent(
    api_key="nz_k_your_key_here",
    container="my-production-app",
)
agent.start()

Using environment variables

All NozieConfig fields support the NOZIE_ prefix. You can skip passing values directly:

bash
# .env
NOZIE_API_KEY=nz_k_your_key_here
NOZIE_CONTAINER=my-production-app
NOZIE_STATS_INTERVAL=60
NOZIE_ERROR_COOLDOWN=120
python
import os
from dotenv import load_dotenv
from nozie import NozieAgent

load_dotenv()

# NozieConfig reads NOZIE_* env vars automatically
NozieAgent(api_key=os.environ["NOZIE_API_KEY"]).start()

Custom backend URL

If you are self-hosting the Nozie backend, specify dashboard_url:

python
from nozie import NozieAgent

NozieAgent(
    api_key="nz_k_your_key_here",
    dashboard_url="https://your-backend.example.com",
).start()
Non-blocking: .start() is non-blocking and returns immediately. Place it at the top of your application startup and let it run in the background.
Reference

NozieAgent

The main entry point. Instantiate it with your API key, call .start(), and the agent begins monitoring in the background.

Constructor

class NozieAgent(
    api_key: str,
    container: Optional[str] = None,
    **kwargs,
)

All keyword arguments are passed through to NozieConfig. See the Configuration page for the full list.

ParameterTypeRequiredDescription
api_key str Yes Your Nozie API key. Starts with nz_k_. Get it from your dashboard.
container Optional[str] No Container name or ID to monitor. If None, all running containers are monitored.
**kwargs No Additional config: dashboard_url, stats_interval, error_cooldown.

Methods

.start()

def start(self) -> None

Starts background monitoring. Spawns a daemon thread named nozie-main which in turn launches the stats loop, events loop, and one log monitor thread per container. Non-blocking — returns immediately.

python
agent = NozieAgent(api_key="nz_k_...")
agent.start()  # returns immediately, agent runs in background

.stop()

def stop(self) -> None

Signals the agent to stop gracefully. Sets the internal stop event and shuts down the thread pool. Because threads are daemon threads, this is optional — the process exit will clean them up automatically.

.restart()

def restart(
    self,
    container_name: str,
    timeout: int = 10,
) -> dict

Restarts a container by name and reports the event to the Nozie backend. Reloads the container metadata first, then issues container.restart(timeout=timeout). Returns a result dict with the following keys:

KeyTypeDescription
container_idstrShort container ID (first 12 chars)
container_namestrContainer name as reported by Docker
restarted_atstrISO 8601 UTC timestamp of the restart
successboolTrue if the restart call succeeded
errorOptional[str]Error message string if the restart failed, otherwise None
python
result = agent.restart("my-production-app", timeout=15)
if result["success"]:
    print(f"Restarted at {result['restarted_at']}")
else:
    print(f"Failed: {result['error']}")
After a successful restart, the agent automatically POSTs to POST /api/v1/agent/restart so the dashboard can log and display the restart history.
Reference

Configuration

NozieConfig is a Pydantic model that validates all configuration fields. It also reads values automatically from environment variables prefixed with NOZIE_.

Fields

FieldTypeDefaultDescription
api_key str required Nozie Product API Key. Obtain from your dashboard under Settings → API Keys.
container Optional[str] None Specific container name or ID. If None, all running and stopped containers are monitored.
dashboard_url str "https://nozie.xyz" Nozie backend base URL. Override for self-hosted deployments.
stats_interval int 30 Seconds between heartbeat stats reports. Lower values give more granular data at the cost of more network traffic.
error_cooldown int 60 Minimum seconds between error reports per container. Prevents flooding the backend when logs are spamming errors.

Environment variables

Because NozieConfig uses env_prefix = "NOZIE_", every field can be set via environment variable. The variable name is the field name uppercased, prefixed with NOZIE_.

VariableCorresponds to
NOZIE_API_KEYapi_key
NOZIE_CONTAINERcontainer
NOZIE_DASHBOARD_URLdashboard_url
NOZIE_STATS_INTERVALstats_interval
NOZIE_ERROR_COOLDOWNerror_cooldown

Example

python
from nozie import NozieAgent

agent = NozieAgent(
    api_key="nz_k_your_key_here",
    container="my-production-app",
    stats_interval=60,        # heartbeat every 60s
    error_cooldown=120,       # max one error report per 2 min
    dashboard_url="https://your-backend.example.com",
)
agent.start()
Reference

Docker Monitoring

Nozie uses the Docker SDK to watch containers, collect stats, and stream logs. Internally this is handled by DockerClientWrapper.

Container targeting

On startup, get_target_containers() is called to find containers to watch:

  • If container is set — fetches the single named container
  • If container is None — lists all containers (running and stopped)

If no containers are found at startup, the agent enters a retry loop, polling for new containers every stats_interval seconds and attaching log monitors as they appear.

Container stats

Every stats_interval seconds, the following metrics are collected per container:

MetricTypeSource
container_idstrFirst 12 chars of Docker container ID
container_namestrDocker container name
statusstrrunning, exited, paused, etc.
cpu_percentfloatCalculated from CPU delta / system delta × num_cores × 100
memory_usage_bytesintmemory_stats.usage from Docker stats API
memory_limit_bytesintmemory_stats.limit from Docker stats API
memory_percentfloatusage / limit × 100
restartsintcontainer.attrs["RestartCount"]
started_atstrISO timestamp from container.attrs["State"]["StartedAt"]
Stopped containers: when a container's status is not running, all numeric metrics are returned as 0. The status field is still reported correctly.

Docker events

In parallel with the stats loop, Nozie watches the Docker event stream filtered to type=container. The following actions trigger an immediate stats report without waiting for the next cycle:

EventReported status
die, stop, kill, oomexited
pausepaused
start, unpause, restartrunning
paused ≠ exited: a paused container is still alive, just suspended — Docker treats it as its own distinct status (restarting / running / paused / exited), and Nozie reports it that way (0.3.0+) instead of conflating a deliberate pause with a crash.

Log streaming

stream_logs(container) is a generator that yields decoded log lines. It streams with tail=100 (last 100 lines on attach) and continues following new lines indefinitely. On timeout or Docker API errors it reconnects automatically after a short sleep.

Reference

Error Detection

Nozie scans every log line against a compiled regex pattern. When a match is found, it captures a rolling buffer of recent log lines as context and reports to the backend.

Detection pattern

The agent uses the following case-insensitive pattern:

regex
(ERROR|Exception|Traceback|FATAL)

This catches the most common failure signatures across Python, Java, Node.js, Go, and generic system logs.

Self-log filter

Lines emitted by the Nozie probe itself are prefixed with [nozie] and are automatically excluded from pattern matching. This prevents the agent's own diagnostic output from triggering false-positive error reports.

Rolling log buffer

Each container maintains its own 50-line rolling buffer. Every incoming log line is appended to this buffer. When an error is detected, the full buffer content is joined and sent as the log_snippet. This gives the AI backend rich context about what happened just before the crash.

python
# Internal buffer logic (simplified)
log_buffer = []

for line in stream_logs(container):
    log_buffer.append(line)
    if len(log_buffer) > 50:
        log_buffer.pop(0)          # drop oldest line

    if error_pattern.search(line):
        snippet = "\n".join(log_buffer)
        report_error(container.name, snippet)

Cooldown mechanism

To prevent flooding the backend when an app crashes in a loop, Nozie enforces a per-container cooldown. After an error report is sent, no further reports are made for that container until error_cooldown seconds have passed (default: 60 seconds).

ScenarioBehavior
First error in container app-AReport sent immediately
Second error in app-A within 60sSilently skipped
Error in app-B (different container)Report sent independently
Error in app-A after 60sReport sent again
Adjust error_cooldown in your config if your app produces bursts of correlated errors. Setting it to 300 (5 min) works well for apps that crash-loop before a restart policy kicks in.
Internals

API Payloads

The agent communicates with the Nozie backend over two REST endpoints. All requests use Bearer token authentication via the API key.

Authentication

Every request includes:

http
Authorization: Bearer <api_key>
Content-Type: application/json

Stats endpoint

http
POST /api/v1/agent/stats

Payload:

json
{
  "agent_version": "0.2.1",
  "containers": [
    {
      "container_id":       "a1b2c3d4e5f6",
      "container_name":     "my-production-app",
      "status":            "running",
      "cpu_percent":       12.5,
      "memory_usage_bytes":134217728,
      "memory_limit_bytes":536870912,
      "memory_percent":    25.0,
      "restarts":          0,
      "started_at":        "2026-03-17T00:00:00Z"
    }
  ]
}

Error endpoint

http
POST /api/v1/agent/error

Payload:

json
{
  "agent_version":   "0.2.0",
  "container_name":  "my-production-app",
  "log_snippet":     "...last 50 log lines as a single string..."
}

Restart endpoint

http
POST /api/v1/agent/restart

Called automatically by agent.restart() after a successful container restart. Payload:

json
{
  "agent_version":   "0.2.1",
  "container_name":  "my-production-app",
  "container_id":    "a1b2c3d4e5f6",
  "restarted_at":    "2026-04-11T12:34:56.789Z",
  "success":         true
}

The backend stores this in the container_restarts table and the dashboard displays the last restart time per container in the monitoring view.

Error handling

The NozieReporter._post() method handles HTTP failures silently — it logs a warning and returns False without raising. The agent continues running even if the backend is unreachable. Retries happen automatically on the next report cycle.

Internals

Architecture

Nozie is split into four focused modules. The agent is the only public entry point — the rest are internal implementation details.

Modules

ModuleClassResponsibility
nozie.agent NozieAgent Public entry point. Orchestrates threads, error pattern matching, cooldown tracking.
nozie.config NozieConfig Pydantic model. Validates all config fields and reads NOZIE_* env vars.
nozie.docker_client DockerClientWrapper Wraps the Docker SDK. Handles container listing, stats collection, event watching, log streaming.
nozie.reporter NozieReporter Thin HTTP client. POSTs stats, error, and restart payloads to the backend. Never raises — logs warnings instead.

Data flow

text
NozieAgent.start()
    │
    ├─► nozie-main thread
    │       │
    │       ├─► stats_loop  ──────────────────────► NozieReporter.report_stats()
    │       │   (every N sec)                              │
    │       │                                              └─► POST /api/v1/agent/stats
    │       │
    │       ├─► events_loop ──────────────────────► NozieReporter.report_stats()
    │       │   (Docker events)                     (status change payloads)
    │       │
    │       └─► log_monitor_loop (per container)
    │               │
    │               ├─► rolling 50-line buffer
    │               ├─► regex match (ERROR|Exception|...)  [case-insensitive]
    │               ├─► skip lines starting with [nozie]   [self-filter]
    │               └─► cooldown check
    │                       │
    │                       └─► NozieReporter.report_error()
    │                                   │
    │                                   └─► POST /api/v1/agent/error
    │
NozieAgent.restart(container_name)
    │
    ├─► DockerClientWrapper.restart_container()
    │       └─► container.reload() + container.restart(timeout)
    │
    └─► NozieReporter.report_restart()
                │
                └─► POST /api/v1/agent/restart

Backend responsibilities

Everything that happens after the POST is handled by the Nozie backend. The library itself has no knowledge of:

  • Nozie analysis or the Anthropic API
  • GitHub PR creation or the GitHub API
  • Repository code reading or patching
  • User accounts, dashboard, or billing

This separation keeps the probe lean and removes the need for any secrets on your server.

N
Nozie AI
Answers from documentation
Hi! I can answer questions about the Nozie library and documentation. What would you like to know?