Skip to main content

Nelieo Substrate Protocol (NSP) Python SDK — give AI agents typed, millisecond-latency access to any running application.

Project description

Nelieo NSP

Nelieo NSP

PyPI Version Python 3.11+ Status Docs

Give AI agents instant, typed, millisecond-latency access to any running application — without source code, without UI automation, without screen scraping.


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

pip install nelieo-nsp

Requirements:

  • Python ≥ 3.11
  • Windows 10/11 (64-bit)
  • NSP Daemon installed and running

AI Framework Extras

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

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 →

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:

axon-daemon.exe run

Step 2 — Get your API Key

Create your free account and generate an API key at:

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

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:

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.

# 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.

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:

# 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.

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

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

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 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.

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

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.

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
API Key & Account platform.nelieo.com
Email Support nelieo.contact@gmail.com

Built by Nelieo · The Execution Layer for Agent-First Software

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nelieo_nsp-0.1.3.tar.gz (42.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nelieo_nsp-0.1.3-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file nelieo_nsp-0.1.3.tar.gz.

File metadata

  • Download URL: nelieo_nsp-0.1.3.tar.gz
  • Upload date:
  • Size: 42.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nelieo_nsp-0.1.3.tar.gz
Algorithm Hash digest
SHA256 371acf4510a0fc345b32d736ac2cc530f52b7632600bcaf48cde69021d0c331d
MD5 d89ac96797c3b42a447a59ca323a73e3
BLAKE2b-256 6243a1778db32a4ef834d83f36a2485b7a5105ede77f01303d5c6d22559f8ebb

See more details on using hashes here.

File details

Details for the file nelieo_nsp-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: nelieo_nsp-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 47.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nelieo_nsp-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 afa593b80f53126942572c38d5c7431d12c0431e894c40eb23a3228b8f4f2b7e
MD5 69a35da9759d3b239d0231a81bf8c029
BLAKE2b-256 703aeef79a33c3006bc8c2cb96f9a041e12bd4f2bace8eedb5ff36e35f3583e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page