Skip to main content

Noxy LangChain Connector

LangChain connector for Noxy human-in-the-loop guardrails. Uses HumanInTheLoopMiddleware to pause agent tool calls, routes encrypted approval prompts to all devices registered for the identity (web, iOS, Android, Telegram), and resumes execution when you poll relay for the settled outcome via noxy-sdk (GetDecisionOutcome).

Installing langchain-noxy pulls in noxy-sdk automatically; you do not need a separate checkout of the Noxy SDK.

Flow

sequenceDiagram
    participant A as LangChain Agent
    participant SDK as noxy-sdk
    participant N as Noxy Relay
    participant D as User Devices

    A->>SDK: send_decision (tool approval)
    SDK->>N: RouteDecision
    N->>D: Deliver to registered devices
    A->>A: interrupt() — state saved to checkpointer
    Note over A: Agent suspended

    loop Poll GetDecisionOutcome
        SDK->>N: get_decision_outcome
        N-->>SDK: pending / approved / rejected / expired
    end

    SDK->>A: Command(resume=HITLResponse)
    A->>A: Continue with approved/rejected tool calls
  1. The agent proposes a guarded tool call.
  2. NoxyHumanInTheLoopMiddleware routes an encrypted actionable to all devices for the identity.
  3. LangChain calls interrupt() — the agent suspends and persists state via a checkpointer.
  4. User responds on any registered device or the decision TTL expires on relay.
  5. Your process calls wait_for_decision_outcome (SDK) or bridge.wait_and_resume(...).
  6. The agent continues with approved or rejected tool calls.

Relay delivers outcomes via gRPC polling (GetDecisionOutcome), with exponential backoff in the SDK.

Requirements

  • Python >= 3.10
  • A LangChain agent created with create_agent and a checkpointer
  • A Noxy app token and target identity (phone, email, user id, or wallet 0x…)

Installation

pip install langchain-noxy

Optional FastAPI example server:

pip install "langchain-noxy[examples]"

Configuration

Variable Required Default Description
NOXY_APP_TOKEN Yes — App token from the Noxy dashboard
NOXY_IDENTITY_ID Yes* — Target identity: phone, email, user id, or wallet
NOXY_ENDPOINT No https://relay.noxy.network Relay gRPC endpoint
MODEL No openai:gpt-4o-mini Chat model for the poll_resume_server example

*Identity is passed to NoxyLangChainBridge(client, identity_id) in code; use the env var when your app reads it from the environment.

Copy .env.example to .env when running repository examples locally (never commit real tokens).

import os
from noxy import NoxyConfig, init_noxy_agent_client

client = init_noxy_agent_client(
    NoxyConfig(
        endpoint=os.environ.get("NOXY_ENDPOINT", "https://relay.noxy.network"),
        auth_token=os.environ["NOXY_APP_TOKEN"],
        decision_ttl_seconds=3600,
    )
)

Quick start

import uuid

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from noxy import NoxyConfig, init_noxy_agent_client

from langchain_noxy import NoxyLangChainBridge

@tool
def transfer_funds(to: str, amount: str) -> str:
    """Transfer funds."""
    return f"Sent {amount} to {to}"

client = init_noxy_agent_client(
    NoxyConfig(
        endpoint="https://relay.noxy.network",
        auth_token="your-app-token",
        decision_ttl_seconds=3600,
    )
)
bridge = NoxyLangChainBridge(client, "user@example.com")

agent = create_agent(
    init_chat_model("openai:gpt-4o-mini"),
    tools=[transfer_funds],
    middleware=[bridge.create_hitl_middleware({"transfer_funds": True})],
    checkpointer=InMemorySaver(),
)

config = {"configurable": {"thread_id": str(uuid.uuid4())}}
# agent.invoke(...) suspends when transfer_funds is proposed; read decision_id from interrupt

final = bridge.wait_and_resume(agent, "<decision_id>")

Manual polling

from noxy.decision_outcome import WaitForDecisionOutcomeOptions

resume_handler = bridge.create_resume_handler(agent)
response = client.wait_for_decision_outcome(
    WaitForDecisionOutcomeOptions(decision_id="<decision_id>", identity_id="user@example.com")
)
final = resume_handler.resume_from_poll_response(
    response, decision_id="<decision_id>", identity_id="user@example.com"
)

Outcome mapping

Noxy relay outcomes map to LangChain HITL decisions (via hitl_response_from_outcome):

  • approved → {"type": "approve"}
  • rejected / expired / timeout → {"type": "reject", "message": "..."}

Poll tuning

Pass WaitForDecisionOutcomeOptions to bridge.wait_and_resume (same fields as noxy-sdk):

Field Default Description
initial_poll_interval_ms 400 First delay between polls
max_poll_interval_ms 30000 Cap between polls
max_wait_ms 900000 Stop polling and resume with timeout outcome
backoff_multiplier 1.6 Exponential backoff factor

API

Symbol Description
NoxyLangChainBridge Wires client, registry, middleware factory, and wait_and_resume
NoxyHumanInTheLoopMiddleware LangChain middleware that routes tool approvals to Noxy
NoxyAgentResumeHandler.wait_and_resume SDK poll loop + Command(resume=...)
NoxyAgentResumeHandler.resume_from_poll_response Resume from one terminal poll
PendingDecisionRegistry Maps decision_id → thread_id for resume
build_hitl_actionable(...) Build actionable payload from HITL action requests
hitl_response_from_outcome(...) Map Noxy outcome to LangChain HITL resume value
parse_webhook_payload(...) Optional: parse webhook-shaped JSON if you bridge events yourself

Examples

Example scripts are maintained in the GitHub repository (they are not shipped inside the PyPI wheel). Clone the repo to run them:

git clone https://github.com/noxy-network/langchain-connector.git
cd langchain-connector
pip install ".[examples]"
cp .env.example .env   # set NOXY_APP_TOKEN and NOXY_IDENTITY_ID
  • examples/basic.py — mock client, no relay required
  • examples/poll_resume_server.py — FastAPI: POST /runs, then POST /runs/wait
python examples/basic.py

export NOXY_APP_TOKEN="your-app-token"
export NOXY_IDENTITY_ID="user@example.com"
uvicorn examples.poll_resume_server:app --reload

Development

For contributors working on this repository:

git clone https://github.com/noxy-network/langchain-connector.git
cd langchain-connector
pip install ".[dev,examples]"
make test
make build
make publish-check

License

MIT

Metadata

Release files for langchain-noxy 1.0.2

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

Source distribution (sdist)

Source distribution for langchain-noxy 1.0.2
File Size Uploaded
langchain_noxy-1.0.2.tar.gz 16.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for langchain-noxy 1.0.2
File Interpreter ABI Platform
langchain_noxy-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 30.0 kB

Release files / langchain_noxy-1.0.2.tar.gz

Download URL langchain_noxy-1.0.2.tar.gz
Size 16.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a8487b92f86d2163ba2b68c96142432fe94591f50d5cd17c525f52eaf9901182
BLAKE2b-256 checksum
How to use checksums
6cc6f6ca3b2137305893521f52e8e1ea3275722f6ae76a2aacc4ce46fc53b1fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / langchain_noxy-1.0.2-py3-none-any.whl

Download URL langchain_noxy-1.0.2-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8eacada7aa69523ac507d28b810f49e2a0c83b0ae8331dcd57bcc09c58d08ddc
BLAKE2b-256 checksum
How to use checksums
d4eadc0755a80a8f70f7b1a4aa0998f14fe89551fe1320506ca62635020357aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

1.0.2 This release

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