Driving NB Shift from your own code
Everything the web page does is one HTTP API. The base URL is
https://api.skillsafe.ai/v1/app-api, every call carries
Authorization: Bearer <token>, and every response is the same envelope.
The task field comes first
NB Shift is one app with four lanes over the same notebook. Every request must carry a
task field; it is what routes the run. The four values are:
task | What it returns | Artifact | Built on |
|---|---|---|---|
audit | Eight reproducibility checks and a repaired running order | cell-order.md | @openai/jupyter-notebook |
port | Six port checks and a complete marimo notebook | notebook.py | @marimo-team/jupyter-to-marimo |
wasm | Five browser-compatibility checks and a substitution list | wasm-changes.md | @marimo-team/wasm-compatibility |
batch | Six schedulability checks and a parameters/runner/failure document | batch_run.md | @marimo-team/marimo-batch |
If task is missing or unrecognised the model picks the closest lane, names the lane it
chose in lane, and says so in the first sentence of summary. The web UI
renders such a reply under the lane you asked for and warns you. Send the field.
The envelope
Success and failure have the same shape, so one branch handles both:
{ "ok": true, "data": { ... } }
{ "ok": false, "error": { "code": "VALIDATION_ERROR", "message": "..." } }
| HTTP | error.code | What it means here |
|---|---|---|
| 401 | UNAUTHORIZED | Missing, malformed or expired token. Get a fresh one from the token page. |
| 402 | INSUFFICIENT_CREDITS | Balance below min_credits. Call /estimate first; it is free. |
| 403 | FORBIDDEN | A guest token on a metered run. Sign in for a personal token. |
| 404 | NOT_FOUND | Wrong slug in the path, or a job id that never existed. |
| 400 | VALIDATION_ERROR | The input did not match the shape below - most often a missing task or notebook. |
| 429 | RATE_LIMITED | Back off and retry. Never tight-loop. |
| 5xx | INTERNAL | Retry once with the same Idempotency-Key so you are not billed twice. |
Step 1 — get a token
Open the token page, sign in, and press Copy shell export. That gives you NB_TOKEN in your shell. A guest token is enough for /me and /estimate; running a lane is metered and needs a personal token. Never paste a token into source control - read it from your own secret store and keep the placeholder "YOUR_TOKEN" in the samples below.
Step 2 — check the session and the balance
GET /me is free. It tells you whether the token is a guest or a person, and what the balance is - which is what the web UI uses to disable the run button before a 402 can happen.
curl -s "https://api.skillsafe.ai/v1/app-api/me" \
-H "Authorization: Bearer $NB_TOKEN"
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="GET")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
print(call("/me"))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
console.log(await call("/me"));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
var rdr io.Reader
_ = bytes.MinRead
req, _ := http.NewRequest("GET", base+"/me", rdr)
req.Header.Set("Authorization", "Bearer "+token)
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/me"))
.header("Authorization", "Bearer " + TOKEN)
.GET()
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
uri = URI(BASE.to_s + '/me')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$ch = curl_init($base . '/me');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
],
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.GetAsync(Base + "/me");
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
Step 3 — price the run
POST /estimate is free, creates no job, and returns model, model_alias, markup_bps, hold_credits and min_credits. The hold differs per lane, because the prompts and output caps differ - estimate the lane you are about to run, never a different one.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/estimate" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/estimate", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/estimate", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/estimate", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/estimate"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/estimate')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/estimate');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/estimate",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
Step 4 — run a lane and poll for the result
POST /run returns {"job_id": "job_..."} immediately; poll GET /jobs/{id} until status is succeeded or failed. Always send an Idempotency-Key header - a content hash of the notebook plus the lane plus an attempt counter. Retrying with the same key returns the same job instead of billing a second one, and because the key includes the lane, two lanes over the same notebook are correctly two distinct runs.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/run", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/run", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
The reply text is on data.output.output as a string. Parse the substring from the first { to the last }; the model is instructed to return no prose, but stripping a stray code fence costs nothing.
Step 5 — stream it instead
POST /run-stream is the same request with Accept: text/event-stream. Concatenate the text of every delta event; the concatenation is the JSON object. This is what the web UI uses to advance its progress card on real signal - each stage watches for the section key that starts it.
curl -N -s -X POST "https://api.skillsafe.ai/v1/app-api/run-stream" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-H "Idempotency-Key: nb-shift:audit:$(date +%s)" \
-d '{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN"
payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
req = urllib.request.Request("https://api.skillsafe.ai/v1/app-api/run-stream", data=json.dumps(payload).encode(), method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "text/event-stream")
req.add_header("Idempotency-Key", "nb-shift:audit:run-1")
chunks = []
with urllib.request.urlopen(req) as r:
for line in r:
line = line.decode().strip()
if not line.startswith("data:"):
continue
evt = json.loads(line[5:].strip())
if evt.get("type") == "delta":
chunks.append(evt["text"])
reply = json.loads("".join(chunks))
print(reply["verdict"], len(reply["findings"]), "findings")
const TOKEN = "YOUR_TOKEN";
const payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
const res = await fetch("https://api.skillsafe.ai/v1/app-api/run-stream", {
method: "POST",
headers: {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
"Accept": "text/event-stream",
"Idempotency-Key": "nb-shift:audit:run-1"
},
body: JSON.stringify(payload)
});
const reader = res.body.getReader();
const dec = new TextDecoder();
let buf = "", out = "";
for (;;) {
const { done, value } = await reader.read();
if (done) break;
buf += dec.decode(value, { stream: true });
const lines = buf.split("\n");
buf = lines.pop();
for (const line of lines) {
if (!line.startsWith("data:")) continue;
const evt = JSON.parse(line.slice(5).trim());
if (evt.type === "delta") out += evt.text;
}
}
console.log(JSON.parse(out).verdict);
// Same request as /run, with Accept: text/event-stream and an
// Idempotency-Key header. Read the response body line by line and
// concatenate the `text` of every `delta` event; the concatenation is
// the JSON object documented above.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run-stream", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
// Same request as /run, with Accept: text/event-stream and an
// Idempotency-Key header. Read the response body line by line and
// concatenate the `text` of every `delta` event; the concatenation is
// the JSON object documented above.
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run-stream"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
# Same request as /run, with Accept: text/event-stream and an
# Idempotency-Key header. Read the response body line by line and
# concatenate the `text` of every `delta` event; the concatenation is
# the JSON object documented above.
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run-stream')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
# Same request as /run, with Accept: text/event-stream and an
# Idempotency-Key header. Read the response body line by line and
# concatenate the `text` of every `delta` event; the concatenation is
# the JSON object documented above.
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run-stream');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
// Same request as /run, with Accept: text/event-stream and an
// Idempotency-Key header. Read the response body line by line and
// concatenate the `text` of every `delta` event; the concatenation is
// the JSON object documented above.
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run-stream",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
Step 6 — one worked request per lane
Same notebook, same everything, one field different. That is the whole router.
task: "audit" — Reproducibility audit
Eight named checks in a fixed order, findings ranked by severity, and artifact.content as a repaired running order in markdown.
The flags sent are the ones relevant to this lane. nb-marimo-redefinition would come back as not-applicable here, because Jupyter permits it - it is the port lane's problem.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/run", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/run", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "audit",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
task: "port" — Port to marimo
Six checks, and artifact.content is a complete runnable marimo notebook as plain Python - no fences, no ellipsis.
Two cells defining the same name at the top level is a hard marimo error, and the defines= headers in the digest are how the model knows which ones collide.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/run", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/run", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "port",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
task: "wasm" — WASM check
Five checks, and artifact.content is a substitution list in markdown, one section per blocker.
The import availability ratings arrive in prescan_facts.flags as nb-wasm-blocked-package, nb-wasm-limited-package and nb-unknown-package.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/run", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/run", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "wasm",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "author",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
task: "batch" — Scheduled batch run
Six checks, and artifact.content carries exactly three ## sections: Parameters, The runner, Failure handling.
Set audience: "ops" for this lane and the answer leads with what breaks unattended rather than with code style.
curl -s -X POST "https://api.skillsafe.ai/v1/app-api/run" \
-H "Authorization: Bearer $NB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}'
import json, urllib.request
TOKEN = "YOUR_TOKEN" # from https://nb-shift.skillsafe.ai/tokens.html
BASE = "https://api.skillsafe.ai/v1/app-api"
def call(path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method="POST")
req.add_header("Authorization", "Bearer " + TOKEN)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req) as r:
env = json.load(r)
if not env.get("ok"):
raise RuntimeError(env["error"]["code"] + ": " + env["error"]["message"])
return env["data"]
payload = {
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
print(call("/run", payload))
const TOKEN = "YOUR_TOKEN"; // from https://nb-shift.skillsafe.ai/tokens.html
const BASE = "https://api.skillsafe.ai/v1/app-api";
async function call(path, payload) {
const res = await fetch(BASE + path, {
method: payload ? "POST" : "GET",
headers: {
"Authorization": `Bearer ${TOKEN}`,
...(payload ? { "Content-Type": "application/json" } : {})
},
body: payload ? JSON.stringify(payload) : undefined
});
const env = await res.json();
if (!env.ok) throw new Error(`${env.error.code}: ${env.error.message}`);
return env.data;
}
const payload = {
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
};
console.log(await call("/run", payload));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
const token = "YOUR_TOKEN" // from https://nb-shift.skillsafe.ai/tokens.html
const base = "https://api.skillsafe.ai/v1/app-api"
func main() {
payload := `{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}`
var rdr io.Reader
rdr = bytes.NewBufferString(payload)
req, _ := http.NewRequest("POST", base+"/run", rdr)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
var env struct {
OK bool `json:"ok"`
Data json.RawMessage `json:"data"`
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
json.NewDecoder(res.Body).Decode(&env)
if !env.OK {
panic(env.Error.Code + ": " + env.Error.Message)
}
fmt.Println(string(env.Data))
}
import java.net.URI;
import java.net.http.*;
public class NbShift {
static final String TOKEN = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
public static void main(String[] args) throws Exception {
String payload = """
{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(BASE + "/run"))
.header("Authorization", "Bearer " + TOKEN)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> res = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
}
}
require 'json'
require 'net/http'
TOKEN = 'YOUR_TOKEN' # from https://nb-shift.skillsafe.ai/tokens.html
BASE = URI('https://api.skillsafe.ai/v1/app-api')
payload = <<~JSON
{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON
uri = URI(BASE.to_s + '/run')
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = payload
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
env = JSON.parse(res.body)
raise "#{env['error']['code']}: #{env['error']['message']}" unless env['ok']
puts JSON.pretty_generate(env['data'])
<?php
$token = 'YOUR_TOKEN'; // from https://nb-shift.skillsafe.ai/tokens.html
$base = 'https://api.skillsafe.ai/v1/app-api';
$payload = <<<'JSON'
{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
JSON;
$ch = curl_init($base . '/run');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$env = json_decode(curl_exec($ch), true);
curl_close($ch);
if (empty($env['ok'])) {
throw new RuntimeException($env['error']['code'] . ': ' . $env['error']['message']);
}
print_r($env['data']);
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
const string Token = "YOUR_TOKEN"; // https://nb-shift.skillsafe.ai/tokens.html
const string Base = "https://api.skillsafe.ai/v1/app-api";
var payload = """
{
"task": "batch",
"notebook": "# document: ipynb (nbformat 4.5)\n# kernel: Python 3 (ipykernel)\n# language: python 3.9.6\n# cells: 5 total, 4 code, 1 markdown, 18 lines\n# stored output: 3 KB (not included below)\n\n# --- cell 0 [markdown]\n# Churn experiments\n\n# --- cell 1 [code] exec=[1] defines=pd,np\nimport pandas as pd\nimport numpy as np\n\n# --- cell 2 [code] exec=[2] defines=df needs=pd\ndf = pd.read_csv(\"/Users/priya/Downloads/churn.csv\")\n\n# --- cell 3 [code] exec=[7] needs=scores\nprint(scores.mean())\n\n# --- cell 4 [code] exec=[4] defines=scores needs=np\nscores = np.random.rand(len(df))\n",
"depth": "standard",
"audience": "ops",
"python": "3.12",
"context": "",
"prescan_facts": {
"flags": [
{
"id": "nb-hidden-state",
"severity": "critical",
"detail": "1 cell references a name defined only in a LATER cell (scores: used in cell 3, defined in cell 4), so the notebook cannot run top to bottom as written"
},
{
"id": "nb-out-of-order",
"severity": "high",
"detail": "1 cell carries an execution count lower than the cell above (cell 4 ran as [4] after cell 3 ran as [7]), so this notebook was not executed top to bottom"
},
{
"id": "nb-no-seed",
"severity": "high",
"detail": "randomness is used in cell 4 with no seed set anywhere, so two runs cannot be compared"
},
{
"id": "nb-absolute-path",
"severity": "high",
"detail": "1 absolute path (/Users/priya/Downloads/churn.csv) ties this notebook to one machine"
}
],
"resources": [
{
"id": "nb-format",
"detail": "document read as ipynb (4.5)"
},
{
"id": "nb-cells",
"detail": "4 code cells, 1 markdown cells, 18 lines"
}
],
"stats": {
"cellCount": 5,
"codeCells": 4,
"importCount": 2,
"topLevelNames": 4
}
}
}
""";
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
var res = await http.PostAsync(Base + "/run",
new StringContent(payload, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(body);
if (!doc.RootElement.GetProperty("ok").GetBoolean())
{
var err = doc.RootElement.GetProperty("error");
throw new Exception($"{err.GetProperty("code")}: {err.GetProperty("message")}");
}
Console.WriteLine(doc.RootElement.GetProperty("data"));
The input contract
| Field | Type | Required | Notes |
|---|---|---|---|
task | string | yes | audit, port, wasm or batch. The router field. |
notebook | string | yes | The cell-structured digest. See below. |
depth | string | no | standard (default), exhaustive, triage. |
audience | string | no | author (default), reviewer, ops. |
python | string | no | 3.12, 3.11, 3.13 or unchanged. |
context | string | no | Anything the notebook does not say. Capped at 2000 characters. |
prescan_facts | object | no | {flags:[{id,severity,detail}], resources:[{id,detail}], stats:{}}. Every flag id sent must come back in coverage_check. |
Building the notebook digest yourself
The web UI never sends raw .ipynb JSON. It sends a digest, because stored outputs are
usually the bulk of a notebook and are usually base64 images that carry no information the model can
use. If you are calling the API directly, produce the same shape:
# document: ipynb (nbformat 4.5)
# kernel: Python 3 (ipykernel)
# language: python 3.11.4
# cells: 12 total, 9 code, 3 markdown, 340 lines
# stored output: 812 KB (not included below)
# --- cell 0 [markdown]
...markdown source...
# --- cell 3 [code] exec=[7] defines=df,scaler needs=raw_path outputs=2 outputs/image
...python source...
exec=[7]is the execution count;exec=never-runmeans it has none.defines=lists names bound at indentation zero - marimo's own rule.needs=lists names the cell references but does not bind.outputs=summarises what the cell produced;TRACEBACKmeans a stored error.- A cell body may carry
# [... N characters cut from the middle of this cell ...]. - Credentials appear as
[redacted-...]. Mask them before you send, as the UI does.
The headers are the model's evidence, not decoration: without defines= it cannot tell you
which cells collide, and without exec= it cannot tell you the notebook ran backwards.
The output contract
One JSON object. The same envelope for every lane; only the inner content differs.
| Field | Type | Notes |
|---|---|---|
lane | string | Equals the task that was sent. |
title, headline, summary | string | Short, specific, about this notebook. |
verdict | string | ready, needs-work or blocked. Anything else is coerced to needs-work. |
checks[] | array | {check, status, evidence, requirement}; status in pass|warn|fail|unknown. A row with an empty check is dropped. |
findings[] | array | {id, severity, area, cell_ref, problem, impact, fix, code}; severity in critical|high|medium|low. A finding with neither problem nor fix is dropped. |
artifact | object | {filename, language, note, content}. The lane's deliverable, in full. |
steps[] | array | Strings, in the order to do them. |
coverage_check[] | array | {flag_id, status, note}; status in confirmed|cleared|not-applicable. |
assumptions[], open_questions[] | array | Strings. |
A reply with empty findings, empty checks and an empty
artifact.content is rejected by the client as unrenderable and retried once with a
reformat note - reusing an idempotency key derived from the same input, so the retry cannot double-bill.
Check the reconciliation. Cross-reference coverage_check[].flag_id
against the flag ids you sent. A flag that was sent and never answered is unreviewed, not cleared -
the web UI prints exactly that, and your own client should too.