Metadata-Version: 2.3
Name: nelieo-nsp
Version: 0.1.3
Summary: Nelieo Substrate Protocol (NSP) Python SDK — give AI agents typed, millisecond-latency access to any running application.
Keywords: ai,agent,automation,nsp,nelieo,substrate,llm
Author: Shourya Jha
Author-email: Shourya Jha <sharmashorya934@gmail.com>
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: httpx[http2]>=0.28.1
Requires-Dist: websockets>=14.1
Requires-Dist: pydantic>=2.10.0
Requires-Dist: loguru>=0.7.3
Requires-Dist: tenacity>=9.0.0
Requires-Dist: anyio>=4.9.0
Requires-Dist: anthropic>=0.40.0 ; extra == 'anthropic'
Requires-Dist: pytest>=8.3.0 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0 ; extra == 'dev'
Requires-Dist: pytest-httpx>=0.35.0 ; extra == 'dev'
Requires-Dist: pytest-timeout>=2.3.0 ; extra == 'dev'
Requires-Dist: mypy>=1.13.0 ; extra == 'dev'
Requires-Dist: ruff>=0.8.0 ; extra == 'dev'
Requires-Dist: coverage[toml]>=7.6.0 ; extra == 'dev'
Requires-Dist: respx>=0.21.0 ; extra == 'dev'
Requires-Dist: langchain-core>=0.3.0 ; extra == 'langchain'
Requires-Dist: openai>=1.60.0 ; extra == 'openai'
Requires-Python: >=3.11
Project-URL: Homepage, https://nelieo.com
Project-URL: Documentation, https://docs.nelieo.com/nsp/python
Project-URL: Repository, https://github.com/Nelieo/Operation-NSP
Project-URL: Bug Tracker, https://github.com/Nelieo/Operation-NSP/issues
Provides-Extra: anthropic
Provides-Extra: dev
Provides-Extra: langchain
Provides-Extra: openai
Description-Content-Type: text/markdown

# Nelieo NSP

<p align="center">
  <img src="https://www.nelieo.com/nelieo-mark.png" alt="Nelieo NSP" width="180" />
</p>

<p align="center">
  <a href="https://pypi.org/project/nelieo-nsp/"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/nelieo-nsp?color=0F0F0F&labelColor=1a1a1a&style=for-the-badge" /></a>
  <a href="#"><img alt="Python 3.11+" src="https://img.shields.io/badge/python-3.11%2B-blue?color=0F0F0F&labelColor=1a1a1a&style=for-the-badge" /></a>
  <a href="https://nelieo.com/nsp/status"><img alt="Status" src="https://img.shields.io/badge/status-beta-orange?color=0F0F0F&labelColor=1a1a1a&style=for-the-badge" /></a>
  <a href="https://docs.nelieo.com"><img alt="Docs" src="https://img.shields.io/badge/docs-docs.nelieo.com-5A5AFF?color=0F0F0F&labelColor=1a1a1a&style=for-the-badge" /></a>
</p>

<p align="center">
  <strong>Give AI agents instant, typed, millisecond-latency access to any running application — without source code, without UI automation, without screen scraping.</strong>
</p>

---

## The Problem with AI Agents Today

Today's AI agents are essentially **blind**. They see pixels on a screen or a string of HTML. To control software, they have to:

- Take a screenshot, ask a vision model to find a button, move a virtual mouse, and click — and hope the button didn't move.
- Parse fragile HTML or DOM trees that break every time a UI is redesigned.
- Write brittle macros that fail the moment an application updates.

This is a fundamental architectural limitation. The AI is working *around* the software, not *with* it.

**Nelieo NSP changes that entirely.**

---

## What is NSP?

**NSP (Nelieo Substrate Protocol)** is a runtime intelligence layer that runs beneath your applications. It injects a lightweight native probe directly into any running process — Java, .NET, Electron, V8/Chrome — and exposes the application's complete live internal state as a typed, structured API.

Your AI agent doesn't look *at* the application. It reads the application's **brain** directly.

```
Your AI Agent ──→ nelieo-nsp SDK ──→ NSP Daemon ──→ [Live Process Memory]
                                       ↓
                          Typed JSON State + Action Schema
```

The result:

| Capability | Traditional Agent | NSP Agent |
|---|---|---|
| Read a value | Vision + OCR + parsing | `session.get_float("balance.total")` |
| Click a button | Find pixels, move mouse | `session.execute("transfer_funds")` |
| React to changes | Poll screenshots every second | Real-time WebSocket stream, `<5ms` |
| Handle UI redesign | Breaks immediately | Zero impact — reading memory, not pixels |
| Confidence score | None | Per-field, cryptographically attested |

---

## Installation

```bash
pip install nelieo-nsp
```

**Requirements:**
- Python ≥ 3.11
- Windows 10/11 (64-bit)
- [NSP Daemon](https://www.nelieo.com/) installed and running

### AI Framework Extras

Install with your preferred AI framework to unlock native tool-calling integration:

```bash
pip install "nelieo-nsp[openai]"      # OpenAI function calling (GPT-4o, o3, etc.)
pip install "nelieo-nsp[anthropic]"   # Anthropic Claude tool use
pip install "nelieo-nsp[langchain]"   # LangChain / LangGraph agents
```

---

## Getting Started

### Step 1 — Install the NSP Daemon

The daemon is a lightweight background process that runs on your machine. It handles the actual process injection and state extraction so your Python code stays clean and portable.

[**Download the NSP Daemon from www.nelieo.com →**](https://www.nelieo.com/)

The installer:
- Registers `axon-daemon.exe` as a Windows Service (auto-starts on login)
- Places the daemon at `C:\Program Files\Nelieo\axon-daemon.exe`
- Creates a default config at `C:\ProgramData\Nelieo\axon.toml`
- Starts the daemon immediately on port **7842**

You can also run the daemon manually for development:
```bash
axon-daemon.exe run
```

### Step 2 — Get your API Key

Create your free account and generate an API key at:

[**platform.nelieo.com →**](https://platform.nelieo.com)

API keys are scoped, rotatable, and tied to your account. They look like this: `nsp_live_sk_...`

### Step 3 — Write your first agent

```python
import asyncio
from nelieo_nsp import NSPClient

async def main():
    async with NSPClient(api_key="nsp_live_sk_...") as client:

        # See every application the daemon is currently tracking
        apps = await client.list_apps()
        for app in apps:
            print(f"  {app.app_name}  |  {app.runtime}  |  pid={app.pid}")

        # Attach to an application by name
        session = await client.attach("Ghidra")

        # Read live internal state — typed, instant, zero-scraping
        project_name = session.get_str("project.name")
        function_count = session.get_int("program.function_count")
        print(f"Project: {project_name} | Functions analyzed: {function_count}")

asyncio.run(main())
```

---

## Core Concepts

### The State Tree

When NSP attaches to an application, it maps every live object in memory into a typed, navigable state tree. You can read any field using dot-notation keys:

```python
state = await client.get_state(pid)

# Read any field from the live application memory
print(state.get("workspace.active_file"))       # str
print(state.get("editor.cursor_line"))          # int
print(state.get("project.has_unsaved_changes")) # bool
```

The daemon refreshes the state continuously. You always get the latest value without polling.

### Actions

NSP doesn't just read applications — it can **execute** internal functions directly. The daemon discovers every callable action inside the application and exposes them with a typed schema.

```python
# List all actions available in this application
schema = await client.get_schema(pid)
for action in schema.actions:
    print(f"  {action.name} ({action.action_class}) — {action.description}")

# Execute a ReversibleWrite action (no confirmation required)
result = await session.execute("open_new_tab")
print(f"Done in {result.latency_ms}ms")

# Execute an IrreversibleWrite action (verify gate required)
result = await session.execute(
    "delete_workspace",
    parameters={"workspace_id": "ws_9f3a"},
    verify=True,
    verify_expression="workspaces.count < 5",
    verify_timeout_ms=3000,
)
```

### Real-Time State Streaming

Subscribe to a live WebSocket stream of state changes. Your agent reacts to what happens inside the application in real-time — no polling, no screenshots.

```python
async with session.watch() as stream:
    async for event in stream:
        print(f"Changed keys: {event.changed_keys}")

        if "compiler.build_status" in event.changed_keys:
            await session.refresh()
            status = session.get_str("compiler.build_status")

            if status == "ERROR":
                # AI agent reads the error and triggers a fix
                error_msg = session.get_str("compiler.last_error")
                await session.execute("open_error_panel")
```

### Waiting for Conditions

Instead of polling in a loop, NSP lets you declare what you are waiting for:

```python
# Wait until the application reaches a specific state
await session.wait_for_key("export.status", "complete")
print("Export finished!")

# Or use a custom predicate
await session.wait_for(
    lambda s: s.get_int("queue.pending_items") == 0,
    timeout=60.0
)
```

---

## AI Framework Integration

### OpenAI (GPT-4o, o3, o4-mini)

NSP automatically generates OpenAI-compatible tool definitions from the application's live action schema. Your agent can call application functions directly using native function-calling.

```python
import openai
from nelieo_nsp import NSPClient
from nelieo_nsp.adapters import NSPToolAdapter

async def run_agent():
    async with NSPClient(api_key="nsp_live_sk_...") as client:
        session = await client.attach("MyApp")
        adapter = NSPToolAdapter(session)

        messages = [{"role": "user", "content": "Summarize the current project status."}]

        while True:
            response = await openai_client.chat.completions.create(
                model="gpt-4o",
                messages=messages,
                tools=adapter.openai_tools(),  # Auto-generated from app schema
            )

            if not response.choices[0].message.tool_calls:
                print(response.choices[0].message.content)
                break

            # Dispatch tool calls directly into the running application
            for tool_call in response.choices[0].message.tool_calls:
                result = await adapter.dispatch_openai_tool_call(
                    tool_call.function.name,
                    tool_call.function.arguments,
                )
                messages.append({"role": "tool", "content": str(result), "tool_call_id": tool_call.id})
```

### Anthropic Claude

```python
from nelieo_nsp.adapters import NSPToolAdapter

adapter = NSPToolAdapter(session)

response = await anthropic_client.messages.create(
    model="claude-opus-4-5",
    tools=adapter.anthropic_tools(),  # Auto-generated from app schema
    messages=[{"role": "user", "content": "Find all critical bugs in the open project."}],
)

for block in response.content:
    if block.type == "tool_use":
        result = await adapter.dispatch_anthropic_tool_call(block.name, block.input)
```

### LangChain / LangGraph

```python
from nelieo_nsp.adapters import NSPToolAdapter

adapter = NSPToolAdapter(session)
langchain_tools = adapter.langchain_tools()  # Drop directly into any LangChain agent

agent = create_react_agent(llm, langchain_tools)
result = await agent.ainvoke({"messages": [("user", "Archive all completed tasks.")]})
```

---

## Supported Runtimes

| Runtime | Examples | Attach Method |
|---|---|---|
| **Java / JVM** | Ghidra, IntelliJ IDEA, any JVM app | JVMTI native injection |
| **.NET / CLR** | Mission Planner, any .NET app | CLR in-process bridge |
| **JavaScript / V8** | Chrome, Electron apps, Node.js | V8 Inspector / CDP |

New runtime support is added continuously. Check [docs.nelieo.com/probes/overview](https://docs.nelieo.com/probes/overview) for the latest.

---

## Safety & Confidence Model

NSP enforces a multi-layer safety model to ensure AI agents cannot execute destructive operations without explicit verification.

Every action in an application is classified at discovery time:

| Action Class | What It Does | Confidence Required | `verify` Required |
|---|---|---|---|
| `Read` | Reads memory state only | None | No |
| `ReversibleWrite` | Modifiable / undoable change | ≥ 0.80 | No |
| `IrreversibleWrite` | Permanent, non-undoable change | ≥ 0.95 | **Yes — enforced** |

The SDK enforces these rules client-side before the request even leaves the machine. An `IrreversibleWrite` called without `verify=True` raises `NSPSafetyError` immediately.

```python
from nelieo_nsp.exceptions import NSPSafetyError, NSPConfidenceTooLowError

try:
    await session.execute("permanently_delete_user", verify=True, verify_expression="audit.log_written == true")
except NSPSafetyError:
    print("Safety gate blocked this action.")
except NSPConfidenceTooLowError as e:
    print(f"Confidence too low: {e.actual:.0%} required {e.required:.0%}")
    await session.refresh(fresh_probe=True)
```

---

## Error Handling

```python
from nelieo_nsp.exceptions import (
    NSPError,                  # Base — catch all NSP errors
    NSPConnectionError,        # Daemon is not running or unreachable
    NSPAuthError,              # Invalid or expired API key
    NSPNotFoundError,          # PID not tracked, or action not in schema
    NSPRateLimitError,         # Rate limit exceeded
    NSPTimeoutError,           # verify gate timed out
    NSPConfidenceTooLowError,  # State confidence below required threshold
    NSPActionError,            # Action dispatched but failed inside the app
    NSPProcessDetachedError,   # Target process exited while attached
    NSPSafetyError,            # Action blocked by safety model
)

try:
    result = await session.execute("send_report", verify=True)

except NSPConnectionError:
    # NSP Daemon is not running — guide the user to start it
    print("Please ensure the NSP Daemon is running. Download: https://www.nelieo.com/")

except NSPProcessDetachedError:
    # Target app closed — wait for it to reopen
    print("Application exited. Waiting for restart...")
    session = await client.wait_for_app("MyApp", timeout=120.0)

except NSPError as exc:
    print(f"NSP error [{exc.code}]: {exc.message}")
```

---

## API Reference

Full API reference is available at **[docs.nelieo.com/sdk/python/overview](https://docs.nelieo.com/sdk/python/overview)**.

### `NSPClient`

| Method | Description |
|---|---|
| `await client.list_apps()` | Returns all applications currently tracked by the daemon |
| `await client.get_state(pid)` | Returns the full typed state tree for a PID |
| `await client.get_schema(pid)` | Returns the full action schema for a PID |
| `await client.attach(name)` | Attach to an application by name, returns `NSPSession` |
| `await client.attach_by_pid(pid)` | Attach by exact PID |
| `await client.wait_for_app(name)` | Block until the named application launches, then attach |
| `await client.ping()` | Returns daemon health and version |

### `NSPSession`

| Method | Description |
|---|---|
| `session.get(key)` | Read a state key (returns raw value) |
| `session.get_str(key)` | Read state key as `str` |
| `session.get_int(key)` | Read state key as `int` |
| `session.get_float(key)` | Read state key as `float` |
| `session.get_bool(key)` | Read state key as `bool` |
| `await session.refresh()` | Fetch the latest state from the daemon |
| `await session.execute(action, ...)` | Execute an action inside the application |
| `session.watch()` | Open a real-time WebSocket stream of state changes |
| `await session.wait_for(predicate)` | Wait until a custom predicate returns `True` |
| `await session.wait_for_key(key, value)` | Wait until `state[key] == value` |

---

## Frequently Asked Questions

**Do I need to install anything on the target machine?**
Only the NSP Daemon needs to be running. No changes are required to the target application, and no source code access is needed.

**Does NSP work with applications I don't own?**
Yes. NSP attaches to any running process on the machine where the daemon is installed. It does not require source code, developer access, or any modification to the target application.

**Is NSP safe to use in production?**
NSP's safety model is built for production. `IrreversibleWrite` actions are gated behind verified pre/post conditions that are evaluated inside the process before and after execution. Read operations are completely non-invasive with zero impact on the target application's performance.

**Which AI models work with NSP?**
Any model. NSP's tool adapters generate standard OpenAI-compatible function definitions, Anthropic tool definitions, and LangChain-compatible tools. Any model that supports function/tool calling — GPT-4o, Claude, Gemini, Mistral, and others — works natively.

**What is the latency?**
State reads: **< 5ms** on first attach, **< 1ms** on cached reads. Action execution: typically **< 10ms** (excluding application-side processing time).

---

## Support & Documentation

| Resource | Link |
|---|---|
| Full Documentation | [docs.nelieo.com](https://docs.nelieo.com/) |
| API Key & Account | [platform.nelieo.com](https://platform.nelieo.com) |
| Email Support | [nelieo.contact@gmail.com](mailto:[nelieo.contact@gmail.com])|


---

<p align="center">
  Built by <a href="https://nelieo.com">Nelieo</a> · The Execution Layer for Agent-First Software
</p>
