Skip to main content

Detrix Python Client

Debug-on-demand observability for Python applications with zero overhead when inactive.

Overview

The Detrix Python client enables your application to be observed by the Detrix daemon without:

  • Code modifications - No print statements or logging changes needed
  • Redeployment - Add metrics to running processes
  • Performance overhead - Zero cost when not actively observing

Installation

# Using uv (recommended)
uv add detrix-py

# Using pip
pip install detrix-py

Quick Start

1. Start the Detrix daemon

detrix serve --daemon

2. Initialize the client in your application

import detrix

# Initialize client - starts control plane, stays SLEEPING (zero overhead)
detrix.init(
    name="my-service",
    daemon_url="http://127.0.0.1:8090",
)

# Your application code runs normally...
def process_request(request):
    data = transform(request)
    return data

3. Enable observability when needed

# Wake up - starts debugger, registers with daemon
detrix.wake()

# Now the daemon can set observation points on any line
# No code changes needed!

# When done observing
detrix.sleep()

Try It

Run the end-to-end example that simulates an AI agent: starts a sample app, wakes it, adds metrics, and captures events.

# 1. Start the Detrix server
detrix serve --daemon

# 2. Run the agent simulation (from clients/python/)
uv run python examples/test_wake.py --daemon-port 8090

Other examples in examples/:

Example Description Run
basic_usage.py Init / wake / sleep cycle uv run python examples/basic_usage.py
trade_bot_detrix.py Long-running app with embedded client uv run python examples/trade_bot_detrix.py
test_wake.py Agent simulation (starts app, wakes, observes) uv run python examples/test_wake.py

API Reference

detrix.init(**kwargs)

Initialize the client. Starts the control plane HTTP server.

Parameters:

  • name (str): Connection name (default: "detrix-client-{pid}")
  • control_host (str): Control plane host (default: "127.0.0.1")
  • control_port (int): Control plane port (default: 0 = auto-assign)
  • debug_port (int): debugpy port (default: 0 = auto-assign on wake)
  • daemon_url (str): Detrix daemon URL (default: "http://127.0.0.1:8090")
  • start_state (str): Initial state "sleeping" or "warm" (default: "sleeping")
  • detrix_home (str): Path to Detrix home directory (default: ~/detrix)
  • health_check_timeout (float): Timeout for daemon health checks in seconds (default: 2.0)
  • register_timeout (float): Timeout for connection registration in seconds (default: 5.0)
  • unregister_timeout (float): Timeout for connection unregistration in seconds (default: 2.0)

detrix.status() -> dict

Get current client status.

Returns:

{
    "state": "sleeping" | "warm" | "awake",
    "name": "my-service-12345",
    "control_host": "127.0.0.1",
    "control_port": 9000,
    "debug_port": 5678,  # 0 if never awake
    "debug_port_active": True,  # True if debug port is actually open
    "daemon_url": "http://127.0.0.1:8090",
    "connection_id": "my-service-12345",  # None if not awake
}

detrix.wake(daemon_url: str = None) -> dict

Start debugger and register with daemon.

Parameters:

  • daemon_url (str): Override daemon URL (optional)

Raises:

  • DaemonError: If daemon is not reachable or URL is invalid

Returns:

{"status": "awake", "debug_port": 5678, "connection_id": "my-service-12345"}

detrix.sleep() -> dict

Stop debugger and unregister from daemon.

Returns:

{"status": "sleeping"}

detrix.shutdown()

Stop control server and cleanup. Call init() again to reinitialize.

State Machine

┌──────────┐         wake()          ┌───────┐
│ SLEEPING │ ──────────────────────►│ AWAKE │
└──────────┘                         └───────┘
    ▲                                   │
    │              sleep()               │
    └────────────────────────────────────┘
  • SLEEPING: No debugger loaded, zero overhead
  • AWAKE: debugpy listening, registered with daemon

Control Plane HTTP Endpoints

The client exposes a local HTTP server for management:

Endpoint Method Description
/detrix/health GET Health check
/detrix/status GET Get current status
/detrix/info GET Get process info
/detrix/wake POST Start debugger + register
/detrix/sleep POST Stop debugger + unregister

Environment Variables

Variable Description
DETRIX_NAME Default connection name
DETRIX_CONTROL_HOST Control plane host
DETRIX_CONTROL_PORT Control plane port
DETRIX_DEBUG_PORT debugpy port
DETRIX_DAEMON_URL Daemon URL
DETRIX_TOKEN Authentication token
DETRIX_HOME Detrix home directory
DETRIX_HEALTH_CHECK_TIMEOUT Timeout for daemon health checks (secs)
DETRIX_REGISTER_TIMEOUT Timeout for connection registration (secs)
DETRIX_UNREGISTER_TIMEOUT Timeout for connection unregistration (secs)

Security

Authentication

The control plane HTTP server has a security-first authentication model:

  • Localhost requests (127.0.0.1, ::1, localhost) are always allowed without authentication
  • Remote requests require a valid Bearer token

To enable remote access:

  1. Set DETRIX_TOKEN environment variable, or
  2. Create ~/detrix/auth-token file with the token

If no token is configured, remote requests are denied by default.

Remote Exposure Guidelines

The control plane is designed for localhost access only by default. If you need to expose it remotely:

  1. Always configure authentication - Set DETRIX_TOKEN or create ~/detrix/auth-token
  2. Use a reverse proxy - Place nginx, HAProxy, or similar in front for:
    • TLS termination (HTTPS)
    • Rate limiting
    • Access logging
    • IP allowlisting
  3. Restrict network access - Use firewall rules to limit which hosts can connect
  4. Protect the token file - Ensure ~/detrix/auth-token has restrictive permissions (chmod 600)

Example nginx configuration:

location /detrix/ {
    # Rate limiting
    limit_req zone=detrix burst=10 nodelay;

    # Proxy to control plane
    proxy_pass http://127.0.0.1:9000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Note: The control plane exposes debugging capabilities. Unauthorized access could allow an attacker to inspect process state. Always treat it as a sensitive endpoint.

Error Handling

The client provides a hierarchy of exception types:

from detrix import DetrixError, ConfigError, DaemonError, DebuggerError

try:
    detrix.wake()
except DaemonError as e:
    print(f"Cannot reach daemon: {e}")
except DebuggerError as e:
    print(f"Debugger error: {e}")
except DetrixError as e:
    print(f"General error: {e}")
  • DetrixError: Base class for all Detrix errors
  • ConfigError: Configuration/initialization errors
  • DaemonError: Communication with daemon failed
  • DebuggerError: debugpy-related errors
  • ControlPlaneError: Control plane server errors

Note: DaemonConnectionError is kept as an alias for DaemonError for backward compatibility.

Known Limitations

1. debugpy Port Remains Open After Sleep

Issue: After calling sleep(), the debug port remains open until the process exits.

Cause: This is a limitation of debugpy itself - it does not support stopping its listener once started. See debugpy#895.

Impact:

  • The debug_port_active field in status remains True after sleep
  • Calling wake() after sleep() reuses the same port
  • The port is only freed when the process terminates

Workaround: This is expected behavior. If you need to fully release the port, you must restart the process.

2. Port Allocation Race Condition (Fixed)

Previous issue: Another process could claim a port between detection and binding.

Resolution: The client now passes port=0 directly to debugpy.listen(), which handles port allocation atomically at bind time. There is no window for another process to claim the port.

Note: If you explicitly specify a port via debug_port parameter or DETRIX_DEBUG_PORT, the standard TOCTOU limitation applies (another process could theoretically bind to that port first). Use port=0 for guaranteed atomic allocation.

Architecture

For detailed architecture documentation, see ARCHITECTURE.md.

Development

# Install dev dependencies
uv sync --all-extras

# Run tests
uv run pytest

# Type check
uv run mypy src/detrix

# Lint
uv run ruff check src/detrix

License

MIT

Release files for detrix-py 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for detrix-py 1.2.0
File Size Uploaded
detrix_py-1.2.0.tar.gz 104.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for detrix-py 1.2.0
File Interpreter ABI Platform
detrix_py-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 135.2 kB

Release files / detrix_py-1.2.0.tar.gz

Download URL detrix_py-1.2.0.tar.gz
Size 104.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ad552940e84c416d92c6e1c4f7bec1e97b47d8baf28f75708e615b7362a5046f
BLAKE2b-256 checksum
How to use checksums
d72fa283d797ed68e25aeba05f91a67affb51bdcf384f5a671b24a5a86eb3edd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / detrix_py-1.2.0-py3-none-any.whl

Download URL detrix_py-1.2.0-py3-none-any.whl
Size 31.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c0eb0cbd1fe5a43fc5a4ce61b7fad3bb68177f9508c50e9e8b3c7f1063c4fc9
BLAKE2b-256 checksum
How to use checksums
09e4a893ec6a825eac98814ac187747bede103d54615bca3994da1bd83fe2960
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page