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

# NSR SDKs

> Four clients for the NSR API — Node, Python, Rust and Go — at tool parity with the MCP server, and a note on which are on a registry today.

Every NSR SDK wraps the same REST API and exposes the same operations the
[MCP server](/stateset-nsr-mcp) does, so a decision made from a Go service and one made by an agent
through MCP are the same call with the same proof. Version numbers track the engine release.

| SDK    | Install                                                  | On a registry?                               |
| ------ | -------------------------------------------------------- | -------------------------------------------- |
| Node   | `npm install stateset-nsr`                               | Yes — `stateset-nsr` 0.9.1                   |
| Python | `pip install stateset-nsr`                               | Yes — `stateset-nsr` 0.9.1                   |
| Rust   | `stateset-nsr-sdk = "0.9"`                               | Yes — `stateset-nsr-sdk` 0.9.1 on crates.io  |
| Go     | `go get github.com/stateset/stateset-nsr/sdks/go@v0.9.0` | Via the Git module path; pin a tag or commit |

<Note>
  The Python and Rust READMEs in the repository still say "not yet published". Both are: PyPI serves
  `stateset-nsr` 0.9.1 and crates.io serves `stateset-nsr-sdk` 0.9.1. The install lines above are the
  ones that work.
</Note>

## Credentials

Every client takes an API key and an organization id, and every one falls back to `NSR_API_KEY`
and `NSR_ORG_ID` in the environment when they are not passed. Explicit arguments win.

## One decision, four languages

`decide` is the flagship call: a verified verdict — `approved`, `denied` or `refused` — with the
proof chain that produced it. `chat` runs the full pipeline on a customer message and returns the
reply, the analysis, and any tool calls that are ready to execute.

<CodeGroup>
  ```typescript Node.js theme={null}
  import { NSRClient } from 'stateset-nsr';

  const nsr = new NSRClient({ apiKey: 'nsr_your_api_key', orgId: 'org_your_org_id' });

  const response = await nsr.chat('I want to cancel my subscription');
  console.log(response.completion.reply);
  console.log(response.analysis.categories[0].category); // "subscription_management"

  // Tool calls the decision has already cleared
  const ready = NSRClient.readyToolCalls(response);
  ```

  ```python Python theme={null}
  from stateset_nsr import NSRClient

  client = NSRClient(
      api_key="nsr_your_api_key",   # or NSR_API_KEY
      org_id="org_your_org_id",     # or NSR_ORG_ID
  )

  # One auditable decision: approved | denied | refused, with a cited proof chain
  decision = client.decide("Can order A1 be refunded?", action="issue_refund")
  print(decision["decision"], decision["proof"]["cited_rules"])

  # Or the full pipeline on a customer message
  response = client.chat("I want to cancel my subscription")
  print(response.completion.reply)
  ```

  ```rust Rust theme={null}
  use stateset_nsr_sdk::NSRClient;

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let client = NSRClient::new("nsr_your_api_key", "org_your_org_id");

      // approved | denied | refused, with a cited proof chain — a typed DecisionResponse
      let decision = client
          .decide("Can order A1 be refunded?", Some("issue_refund"), "safe", None, None)
          .await?;
      println!("{} ({:.2}) cited: {:?}",
          decision.decision, decision.confidence, decision.proof.cited_rules);

      // Verify the proof independently — no trust in the engine required
      if let Some(bundle) = decision.verifiable_bundle.clone() {
          let verdict = client.verify_proof(bundle).await?;
          assert!(verdict.verified);
      }
      Ok(())
  }
  ```

  ```bash Go theme={null}
  go get github.com/stateset/stateset-nsr/sdks/go@v0.9.0
  # The module's README in sdks/go carries the client example for this version.
  ```
</CodeGroup>

<Tip>
  A `refused` verdict is the correct, safe result when the engine lacks a premise — not an error to
  retry. Ask for the missing fact or escalate. The [decisions page](/stateset-nsr-decisions) explains
  what each verdict means and what the proof chain lets you check.
</Tip>

## Verifying webhooks

The Python SDK also ships `verify_webhook_signature` for NSR's outbound webhooks; the other three
carry an equivalent. Verify against the raw request body with a constant-time comparison.

## Related

* [Verified Decisions API](/stateset-nsr-decisions) — the REST contract every SDK wraps
* [NSR MCP server](/stateset-nsr-mcp) — the same 36 operations as agent tools
* [Agent Gate](/stateset-nsr-agent-gate) — putting a decision in front of every tool call
