> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nelieo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# nelieo-nsp Python SDK: Package and Symbol Reference

> Everything exported by nelieo-nsp: NSPClient, NSPSession, CLR/JVM proxies, typed models, enums, streaming, and environment variable configuration.

The `nelieo-nsp` package is the official Python SDK for the Nelieo State Protocol. It gives you a fully async, type-safe interface for reading application state, executing actions, and streaming real-time changes from any process the NSP daemon is tracking — whether that process is a browser tab, a .NET desktop app, or a JVM service.

## Installation

Install the package with pip:

```bash theme={null}
pip install nelieo-nsp
```

<Note>
  `nelieo-nsp` requires **Python 3.11 or later**. All dependencies are installed automatically — you do not need to install `httpx`, `pydantic`, `websockets`, or `loguru` separately.
</Note>

## Requirements

| Dependency   | Minimum Version | Purpose               |
| ------------ | --------------- | --------------------- |
| Python       | 3.11            | Core runtime          |
| `httpx`      | 0.27+           | Async HTTP transport  |
| `pydantic`   | v2 (2.7+)       | Data model validation |
| `websockets` | 13.0+           | WebSocket streaming   |
| `loguru`     | 0.7+            | Structured logging    |

## Package Structure

The importable package is `nelieo_nsp`. Its internal layout is:

```
nelieo_nsp/
├── __init__.py      # Public API — all exported symbols re-exported here
├── client.py        # NSPClient — the primary entry point
├── session.py       # NSPSession, CLRSessionProxy, JVMSessionProxy
├── models.py        # Pydantic data models: SubstrateState, ActionSchema, ...
├── watch.py         # StateStream and open_state_stream (streaming)
└── exceptions.py    # Full exception hierarchy
```

You only need to import from `nelieo_nsp` directly — everything public is re-exported from `__init__.py`.

## Exported Symbols

Import any of these directly from `nelieo_nsp`:

```python theme={null}
from nelieo_nsp import (
    # Primary client
    NSPClient,

    # Session interfaces
    NSPSession,
    CLRSessionProxy,          # .NET helpers — accessed as session.clr
    JVMSessionProxy,          # Java helpers — accessed as session.jvm

    # Data models
    SubstrateState,           # Full state snapshot for a process
    AppSummary,               # Lightweight descriptor returned by list_apps()
    ActionSchema,             # Metadata and signature for a single action
    ActionParameter,          # Parameter descriptor within ActionSchema
    ActionRequest,            # Low-level action dispatch request body
    ActionResponse,           # Result returned by execute() / execute_action()
    VerificationResult,       # Post-action verification outcome
    StateChangeNotification,  # Single event yielded by StateStream

    # Enums
    RuntimeKind,              # v8 | jvm | clr | native | unknown
    Reversibility,            # read | reversible_write | irreversible_write

    # Streaming
    StateStream,              # Async iterator of StateChangeNotification

    # Exceptions
    NSPError,
    NSPAuthError,
    NSPConnectionError,
    NSPNotFoundError,
    NSPRateLimitError,
    NSPTimeoutError,
    NSPConfidenceTooLowError,
    NSPIrreversibleNotConfirmedError,
)
```

## Environment Variable Configuration

You can configure the SDK entirely through environment variables, avoiding hardcoded credentials in source code:

```bash theme={null}
# API key — required unless you pass api_key= to NSPClient directly
export NSP_API_KEY=sk_nsp_a1b2c3...

# Daemon host — defaults to 127.0.0.1
export NSP_HOST=127.0.0.1

# Daemon port — defaults to 7842
export NSP_PORT=7842
```

When `NSP_API_KEY` is set, you can construct `NSPClient()` with no arguments:

```python theme={null}
import nelieo_nsp as nsp

async with nsp.NSPClient() as client:   # reads NSP_API_KEY from environment
    apps = await client.list_apps()
```

## Quick Reference

The following example demonstrates the complete usage pattern from connection to streaming:

```python theme={null}
import asyncio
import nelieo_nsp as nsp

async def main():
    # ── Connect ──────────────────────────────────────────────────────────
    async with nsp.NSPClient(api_key="sk_nsp_...") as client:

        # ── Discover tracked applications ─────────────────────────────
        apps = await client.list_apps()
        for app in apps:
            print(f"{app.app_name}  pid={app.pid}  conf={app.confidence:.2f}")

        # ── Attach to an app by name ───────────────────────────────────
        session = await client.attach("Gmail")

        # ── Read typed state values ────────────────────────────────────
        unread  = session.get_int("inbox.unread_count")
        subject = session.get_str("inbox.emails[0].subject")
        print(f"Unread: {unread}  Latest: {subject}")

        # ── Inspect available actions ──────────────────────────────────
        for name, schema in session.actions.items():
            print(f"  {name}: {schema.signature}  [{schema.reversibility}]")

        # ── Execute an action ──────────────────────────────────────────
        result = await session.execute(
            "archive",
            parameters={"email_id": session.get_str("inbox.emails[0].id")},
        )
        print(f"Archived: {result.success}  latency={result.latency_ms}ms")

        # ── Stream real-time state changes ─────────────────────────────
        async with session.watch() as stream:
            async for event in stream:
                print(f"Changed keys: {event.changed_keys}")
                await session.refresh()
                break  # one event for demo

asyncio.run(main())
```

## Next Steps

<CardGroup cols={2}>
  <Card title="NSPClient" icon="plug" href="/sdk/python/client">
    Manage connections, list apps, get state, execute actions, and attach sessions.
  </Card>

  <Card title="NSPSession" icon="layers" href="/sdk/python/session">
    Read state, execute actions, stream changes, and wait for conditions.
  </Card>

  <Card title="CLR Helpers" icon="square-terminal" href="/sdk/python/clr">
    Read .NET fields, invoke methods, and walk the CLR heap for .NET apps.
  </Card>

  <Card title="JVM Helpers" icon="coffee" href="/sdk/python/jvm">
    Access Java fields and invoke methods via JNI reflection for JVM apps.
  </Card>

  <Card title="Streaming" icon="radio" href="/sdk/python/streaming">
    Subscribe to WebSocket state-change events in real time.
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/sdk/python/error-handling">
    Understand every exception the SDK can raise and how to recover.
  </Card>
</CardGroup>
