nace-kit
Multi-key client, presets, CLI and MCP server for the nace.ai Drex API — classify text or JSON with calibrated probabilities, from Python or any MCP-speaking agent.
English | 简体中文
Contents
- Why this exists
- Quick start
- How it works
- Comparison with the official SDK
- Question types
- Document pipeline
- MCP for agents
- CLI
- FAQ
- Contributing
- License
Why this exists
Drex answers typed questions about any text or JSON with calibrated probabilities — great for routing tickets, triaging issues, grading replies. The official nace-sdk wraps the whole API; nace-kit wraps the operations around it:
- Key pool — several API keys work as one. A dead key (401) or an exhausted quota (429) fails over to the next key mid-request.
- Response cache — Drex answers are deterministic, so identical requests are served from an LRU cache instead of billed again.
- Usage metering — calls and tokens, per key, always visible in
client.usage. - Presets & typed answers —
urgency(),sentiment(),severity(),priority()out of the box; pydantic questions and responses throughout. - Document pipeline — parse / extract / ground over the official SDK with the same key pool (
[docs]extra).
Quick start
Requires Python 3.11+ (Windows / macOS / Linux) and one or more API keys from the console.
pip install nace-kit # or: uv add nace-kit / uvx nace-kit for one-off use
export NACE_API_KEYS="nace_sk_...,nace_sk_..." # pool of keys; NACE_API_KEY for one
from nace_kit import NaceClient, presets
client = NaceClient() # defaults to drex-latest
# binary question -> probability of yes
r = client.classify("Help! My payouts have been failing for 3 days.", presets.urgency())
r.answers["is_urgent"].noul # 0.7161
# state can be any JSON; questions batch into ONE request
r = client.classify(
{"ticket": "#42", "subject": "payout failure", "days_stuck": 3},
[presets.urgency(), presets.severity(), presets.priority()],
)
client.models() # available models; also a cheap key health check
client.usage # {'nace_sk_wn…': {'calls': 12, 'input_tokens': 300, ...}}
Async works the same: from nace_kit import AsyncNaceClient.
How it works
| Failure | Behaviour |
|---|---|
| 401 / 403 (bad or dead key) | rotate to the next key immediately |
| 429 (quota), several keys configured | rotate to the next key immediately |
| 429, single key configured | retry the same key with backoff (honours Retry-After) |
| 408 / 5xx / network / timeout | retry the same key — exponential backoff + jitter, Retry-After aware, 30 s total budget — then rotate |
| 4xx (payload rejected) | raise immediately, no retries (NaceBadRequest) |
Keys are validated at construction (nace_sk_ + 43 chars); retries (max_retries, backoff_*, retry_budget), cache size and timeouts are constructor parameters.
Comparison with the official SDK
official nace-sdk |
nace-kit |
|
|---|---|---|
Classification API (all three question types, any-JSON state, models listing, typed objects) |
✅ | ✅ |
| Multi-key pool with failover | ❌ single key | ✅ |
| LRU response cache | ❌ | ✅ |
| Per-key usage metering | ❌ | ✅ |
Backoff retries, Retry-After, budget |
✅ | ✅ (combined with rotation) |
| Question presets | ❌ | ✅ |
| Document pipeline (upload/parse/extract/jobs) | ✅ | ✅ via the official SDK ([docs] extra) |
nace login credential file |
✅ | ❌ env vars |
| CLI + MCP server in one package | ❌ separate nace-mcp |
✅ |
Question types
| Type | criteria |
Answer |
|---|---|---|
noul |
optional {"true": "…", "false": "…"} outcome descriptions |
{"noul": 0..1} — probability of yes |
choice |
{label: description} — one label wins |
{"choice": "billing", "probabilities": {...}, "confidence": …} |
score |
["low", "medium", "high"] — ordered levels |
{"score": 1.31, "legend": […], "probabilities": {...}, "confidence": …} |
from nace_kit import presets as p
p.noul("Refund?", true="wants money back")
p.choice("What is this?", {"billing": "payments", "technical": None})
p.score("How angry?", ["calm", "annoyed", "angry", "furious"])
Pick your own threshold on the probabilities rather than treating them as a verdict.
Document pipeline
The document operations wrap the official nace-sdk (MIT) — their API surface, our key pool on top:
pip install "nace-kit[docs]"
from nace_kit import DocsClient
docs = DocsClient() # same NACE_API_KEYS pool; rotates on 401/429
job = docs.parse("https://example.com/report.pdf",
output={"formats": ["markdown"]}, wait=120)
job.result["document"]["markdown"]
parse / split / classify_document / extract / ground create jobs and (with wait) poll them to completion; docs.job(id), docs.wait(id), docs.jobs() manage them afterwards. Every create is idempotency-keyed, so a key rotation mid-call never bills a second job. AsyncDocsClient mirrors everything.
MCP for agents
One registration, every project. ZCode (~/.zcode/cli/config.json → mcp.servers):
"nace": {
"type": "stdio",
"command": "uvx",
"args": ["nace-kit-mcp"],
"env": { "NACE_API_KEYS": "nace_sk_...,nace_sk_..." }
}
Claude Desktop / Cursor: same shape under mcpServers.
Tools: classify (full batch interface), ask (single question over noul / score / choice), list_models, and — with the [docs] extra installed — parse_document, extract_data, get_document_job.
Prefer a skill? nace-kit --install-skill copies an Agent Skill (SKILL.md) to ~/.agents/skills/ (or --claude for ~/.claude/skills/), so agents get usage guidance — question phrasing, batching, thresholds — even without the MCP registration.
CLI
nace-kit "Camera 3 is showing a black screen." --no-cache
nace-kit "..." --ask "How angry is the user?" --kind score --levels calm annoyed angry furious
nace-kit "..." --ask "What is this about?" --kind choice --options billing:"payment issues" technical:"bugs"
nace-kit --models
FAQ
Is the cache safe?
Drex answers are deterministic for identical input (same model, state, questions), so caching is exact. Pass cache_size=0 to disable.
Which model does it call?
drex-latest by default, which nace.ai moves forward on announced dates; pin with NaceClient(model="drex-v2.0") if you need reproducibility.
Where do keys go?
NACE_API_KEYS (comma-separated pool) or NACE_API_KEY. For agents, put them in the MCP server's env block. Never in code.
Contributing
Issues and PRs are welcome at lincong1987/nace-kit.
uv sync # httpx, mcp, pytest
uv run pytest -q # unit tests — no network or keys needed
License
MIT © nace-kit contributors.
Metadata
Release files for nace-kit 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nace_kit-0.3.0.tar.gz | 79.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nace_kit-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 102.3 kB
Release files / nace_kit-0.3.0.tar.gz
| Download URL | nace_kit-0.3.0.tar.gz |
|---|---|
| Size | 79.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c9d8f0d198d48aa68f8907ef23ae05a64d672ce96f9ecddb51b79f47bb2d0bd8
|
|
BLAKE2b-256 checksum How to use checksums |
a11c8b42939efc1a5903458625b2faeb92859bc3108d2d0c3feeae8145ff1444
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / nace_kit-0.3.0-py3-none-any.whl
| Download URL | nace_kit-0.3.0-py3-none-any.whl |
|---|---|
| Size | 23.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8032d3409c088ef8ca184dc8f68ab6e7c34e9847e742e5d179f7548d859845f5
|
|
BLAKE2b-256 checksum How to use checksums |
0587c20ccac7a2f6f914110637e04ed2f292a9fe14aa828d27d379c344f6c099
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log