Nexura Python SDK
Trace an agent running on your own infrastructure, or deploy a Python HTTP service to Nexura-managed hosting. Both modes use the same trace viewer. This package is independent of Langflow and the existing langflow_sdk.
Current release: preview (0.x). APIs may change between minor versions.
Install and connect
pip install 'nexura[cli,langchain,otel]'
# Uses the hosted Nexura API by default; set NEXURA_URL only for a self-hosted instance.
# Set NEXURA_API_KEY through your environment/secret manager.
# Create the key in Settings → API Keys with traces:write.
Only httpx is required by the core package. Python 3.10–3.14 is declared; automated checks in this workspace use Python 3.13 for the standalone SDK and 3.14 for backend integration.
import nexura
nexura.init(service="support-agent") # call before constructing/running agents
@nexura.span(type="tool")
def lookup(question):
return {"answer": "Your result"}
with nexura.trace("support-request", session_id="conversation-123"):
result = lookup("Where is my order?")
nexura.shutdown()
For an existing LangChain/LangGraph program, nexura.init() installs the callback hook. Alternatively run it without editing the entry point:
nexura run -- python agent.py
run launches a child process and preserves its exit code. Its private sitecustomize bootstrap initializes Nexura; it does not modify global site-packages. If your application relies on an existing sitecustomize, initialize Nexura explicitly in your entry point instead.
Integration coverage
| Application | Integration | Usage source |
|---|---|---|
| LangChain / LangGraph | Automatic callback hook after init() |
LLM generation usage_metadata or provider llm_output |
| Framework emitting OpenTelemetry spans | Nexura span processor, attached to the installed OTel provider | GenAI/OpenInference token attributes |
| Custom Python agent or other Python framework | trace context and span decorator/context |
Explicit span.usage(...) from the provider response |
| JavaScript / other languages | HTTP ingestion contract below | Caller supplies spans and measured usage; no native SDK yet |
An OTel processor collects existing instrumentation; it does not instrument every framework by itself. Install and configure your framework's own instrumentor if needed. Avoid enabling two independent instrumentors for the same LLM calls, which can create duplicate telemetry. Non-OTel frameworks such as native OpenAI Agents require an OTel bridge or explicit spans in this release.
Tested adapters include an actual LangGraph graph, LangChain callbacks and the OpenTelemetry SDK. Other frameworks are not certified as automatically supported.
Token usage and correlation headers
Headers associate requests; they cannot reveal a model's token usage. Counts come from provider response metadata. Streaming requests need the provider's final usage event; interrupted streams or providers that omit usage leave the count unavailable. Nexura does not fabricate an estimate. Cached/reasoning details are retained when supplied by the integration.
with nexura.trace("answer") as run:
with run.span("model-call", type="llm", model="your-model") as call:
response = your_provider_call()
call.usage(
input_tokens=response.usage.input_tokens,
output_tokens=response.usage.output_tokens,
)
Use the actual usage field names of your provider. Parent totals are excluded when leaf spans already contain usage. Missing usage attributes stay absent; the existing dashboard's aggregate may display zero when no usage was reported.
# Send to your own downstream service:
request_headers = nexura.headers() # W3C traceparent, never NEXURA_API_KEY
# In that downstream service:
with nexura.trace("downstream", headers=incoming_headers):
...
Each service exports a separate local tree with the shared distributed trace ID in span attributes. The UI does not yet merge distributed service trees into one waterfall.
Behavior and privacy
- Sync/async functions and sync/async generators preserve results, exceptions and streaming values. Close partially consumed generators (
close/aclose). Await child work before closing its parent trace. - Concurrent threads/tasks have separate active contexts. Explicitly propagate context into custom thread pools if the work should belong to a parent trace.
- An escaping exception marks its originating span; the overall trace is failed without marking every ancestor failed.
- Prompts/outputs are not automatically captured by default. Enable
capture_content=Trueto opt in. Explicitspan.input()/output()always capture their argument. - Sensitive dictionary key names are redacted. Free-form strings, exception messages, source code and user-defined metadata are not a comprehensive secret-detection boundary.
- Export is synchronous and bounded: HTTP timeout 3 seconds with two retries by default. It can add latency to an async task. Failures warn and preserve application execution; delivery is best effort, without a persistent disk queue.
- Maximum 1,000 spans / 4 MB per completed trace. Oversized trees are dropped with a warning. Split long-running agents into individual request traces. The API also limits tree depth to 64.
flush()ends incomplete traces; call it only after work completes.shutdown()flushes and closes owned connections. Abrupt termination cannot guarantee export.
Explicit init arguments override environment variables, which override saved login credentials. Supported variables: NEXURA_URL, NEXURA_API_KEY, NEXURA_SERVICE, NEXURA_ENVIRONMENT, NEXURA_DEPLOYMENT. Remote URLs must use HTTPS; localhost HTTP is allowed for development.
Nexura-managed hosting
Hosting must be provisioned by the operator first; see HOSTING.md. Your own infrastructure needs only SDK tracing and is never deployed to by this CLI.
nexura login --url https://your-nexura-api.example.com
nexura init
# Review nexura.json. command must start an HTTP server on 0.0.0.0:$PORT.
nexura secret my-agent MODEL_API_KEY
nexura deploy
nexura status DEPLOYMENT_ID
nexura logs DEPLOYMENT_ID
nexura rollback PREVIOUS_SUCCESSFUL_DEPLOYMENT_ID
nexura stop DEPLOYMENT_ID
Login prompts privately for a key and stores it in ~/.nexura/credentials with mode 0600. A developer key needs deploys:manage; trace reads additionally need traces:read; invocation needs agents:execute. Hosted containers receive a separate traces:write key, never your developer key.
nexura init suggests an entry point and environment names, not values. Review and edit it. Example:
{
"name": "my-agent",
"python": "3.12",
"command": ["python", "app.py"],
"port": 8080,
"environment": ["MODEL_API_KEY"]
}
Dependencies come from requirements.txt or pyproject.toml. A plain batch script is not a hosted HTTP service; use the included HTTP example as a starting point. CPU/GPU selection, arbitrary Dockerfiles, JavaScript hosting and scheduled jobs are not implemented.
The CLI lists files before upload. It excludes common credentials, .env*, virtual environments, build output and symlinks. .nexuraignore and .gitignore support simple glob exclusions, not full Git negation semantics. Review that list for application-specific secrets. Source uploads are limited to 50 MB, with 10 MB per file.
Deployment states: queued → building → deploying → live or failed. “Ready” in the UI means the revision deployed successfully; only the revision currently receiving traffic can be invoked through its deployment ID. Rollback moves traffic to a prior immutable revision. stop deletes the whole service, then revokes all its runtime trace keys; traces/history remain. Stop is rejected while another deployment for that service is in progress.
Runtimes are IAM-private. Send requests through /api/v1/deploys/DEPLOYMENT_ID/invoke/YOUR_PATH with an agents:execute Nexura API key. The proxy authenticates ownership and sends a Google identity token to the runtime. It supports streaming responses and bounds request bodies to 4 MB. It currently forwards content-type and accept, not arbitrary application headers or WebSockets.
HTTP ingestion
POST /api/v1/traces, JSON body, header x-api-key with traces:write.
The backend request models define the contract: trace UUID/name/start/end/service and a bounded flat list of span UUIDs, parent UUIDs, type, status, times, attributes and optional input/output/error. Timestamps must include a timezone. Each parent must be in the same envelope; cycles and duplicate IDs are rejected.
The server derives ownership and source from authentication; client user_id/source fields are rejected. Retries retain the same trace/span IDs. Cross-owner or cross-trace ID collisions return 409. Read the tree from /api/v1/monitor/traces/{id} with traces:read.
Development
uv sync --project src/nexura-sdk --all-extras
uv run --project src/nexura-sdk pytest src/nexura-sdk/tests
uv build --wheel src/nexura-sdk
The SDK is deliberately not part of the Langflow uv workspace. The preview needs live cloud validation before offering managed hosting to customers.
Release files for nexura 0.1.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 | |
|---|---|---|---|
| nexura-0.1.0.tar.gz | 127.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nexura-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 150.1 kB
Release files / nexura-0.1.0.tar.gz
| Download URL | nexura-0.1.0.tar.gz |
|---|---|
| Size | 127.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
617c47e30a9ee9df7c42c5e2e18dc42b713e312416b1cbf3151642225aa48363
|
|
BLAKE2b-256 checksum How to use checksums |
b6bb92ceb8283a93eafd7b5f9018ef1ca2e16e85629198620f12fba25f438330
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|
Release files / nexura-0.1.0-py3-none-any.whl
| Download URL | nexura-0.1.0-py3-none-any.whl |
|---|---|
| Size | 22.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e6fcd844e1000641877d243a6c98ad94055536f3b884d5c0a5c51ded04ccdc2a
|
|
BLAKE2b-256 checksum How to use checksums |
7ddce1d5aad393dfdb83d56d75c13b9c0dcd488755b4011beb4442a10099827c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|