Skip to main content

qunivex

Official Python SDK for the Qunivex API — run your AI agents, search your knowledge base, and manage your projects from Python.

pip install qunivex
from qunivex import Qunivex

qx = Qunivex(api_key="qvx-live-...")

print(qx.chat("QXA-8MQ7KN2A", "What plans do you offer?").content)

Create a key on the API page in your dashboard. Full reference: qunivex.com/docs/api


model is an agent, not a foundation model

This is the one thing to know before you start. A Qunivex agent is a whole configured pipeline — system prompt, knowledge base, tools, MCP servers, sub-agents, guardrails, workflow — built in your dashboard. Which LLM runs inside it is the agent's own setting, not something the caller picks.

So model takes a QXA- agent id. A QXP- project id also works and resolves to that project's main agent.

Prefix Names Example
QXP- Project QXP-1DM2J8K0
QXA- Agent (main or sub-agent) QXA-8MQ7KN2A

Both are on your project's Overview page.

Setup

qx = Qunivex(api_key="qvx-live-...")

Or set QUNIVEX_API_KEY in the environment and pass nothing — worth preferring, since a key in source is a key in version control.

qx = Qunivex()                                  # reads QUNIVEX_API_KEY
qx = Qunivex(timeout=60, max_retries=4)         # tune transport
with Qunivex() as qx: ...                        # closes the HTTP session

Rate limits and transient server errors are retried automatically with exponential backoff and jitter, honouring Retry-After. A quota 429 is not retried — waiting will not help.

Chat

reply = qx.chat("QXA-8MQ7KN2A", "What plans do you offer?")

reply.content            # the text
reply.total_tokens       # usage for this turn
reply.blocked            # True if a guardrail stopped it
reply.raw                # the untouched API payload

Stream it:

for piece in qx.stream("QXA-8MQ7KN2A", "Tell me about Pro"):
    print(piece, end="", flush=True)

Multi-turn

The API is stateless — every request carries the full history, exactly like OpenAI's. That makes each call reproducible and leaves the context window under your control.

Manage the transcript yourself:

history = [{"role": "user", "content": "What plans do you offer?"}]
r = qx.chat(AGENT, history[-1]["content"])
history.append({"role": "assistant", "content": r.content})

…or let a Conversation do it:

convo = qx.conversation("QXA-8MQ7KN2A", system="Be concise.")

convo.send("What plans do you offer?")
convo.send("Which suits two people?")     # remembers the first turn

convo.messages          # the running transcript — mutable, trim it if you like
convo.reset()           # start over, keeping the system message

A Conversation also generates one conversation_id and sends it with every turn, so the whole exchange is grouped together in your dashboard's Logs.

Raw OpenAI shape

When you need a field the wrappers do not surface:

resp = qx.completions.create(
    model="QXA-8MQ7KN2A",
    messages=[{"role": "user", "content": "Hello"}],
    temperature=0.2,
)
resp["choices"][0]["message"]["content"]

Semantic search

Retrieval only — no model call, so it is far cheaper and faster than a completion. Ideal for adding search to your own site over content already in Qunivex.

for hit in qx.search("QXP-1DM2J8K0", "refund policy", top_k=3):
    print(round(hit.score, 3), hit.source, hit.text[:100])

score is a relevance figure in (0, 1] — higher is better. Pass agent= to search a sub-agent's own knowledge base instead of the project's.

If the embedding provider is down this raises ServiceUnavailableError rather than returning an empty list, so "nothing matched" and "search is broken" never look the same.

Projects

for p in qx.projects.list():
    print(p.id, p.name)

project = qx.projects.retrieve("QXP-1DM2J8K0")

project.name                        # 'Acme Support'
project.main_agent.system_prompt
project.main_agent.model
project.sub_agents                  # [AgentInfo, ...]
project.knowledge.documents         # 12

project.update(
    name="Acme Support",
    main_agent={"system_prompt": "Be concise and always cite a source.",
                "temperature": 0.3},
)

project.chat("What plans do you offer?")     # via the main agent
project.search("refund policy")

Editable at the top level: name, description. Under main_agent: name, system_prompt, model, temperature, max_tokens, memory, widget_enabled. Only fields you pass are changed.

Knowledge base

docs = project.documents

docs.upload("handbook.pdf")
docs.add_text("faq.txt", "Q: Do you ship internationally? A: Yes…")

for d in docs.list():
    print(d.filename, d.status, d.chunks, d.tokens)

docs.delete(doc_id)

Indexing happens before the response returns, so the Document you get back already carries its final status and chunk count — nothing to poll. Supported: PDF, DOCX, TXT, MD, HTML, JSON, XML, RTF, YAML and other plain-text formats.

Uploads count against your plan's knowledge-base token budget.

Discovery & usage

for m in qx.models():
    print(m.id, m.name, m.project_name, m.model_name)

u = qx.usage()
print(f"{u.api_calls_used}/{u.api_calls_limit} calls, {u.api_calls_remaining} left")

Neither counts against your quota.

Errors

from qunivex import (
    QunivexError, AuthenticationError, PermissionDeniedError,
    NotFoundError, RateLimitError, QuotaExceededError,
)

try:
    qx.chat(AGENT, "hello")
except QuotaExceededError:
    ...                     # monthly allowance spent — upgrade or wait
except RateLimitError as e:
    ...                     # burst limit; e.retry_after has the wait
except AuthenticationError:
    ...                     # bad or revoked key
except QunivexError as e:
    print(e.status, e.code, e.message)

Every error subclasses QunivexError, so that last clause is a complete catch.

NotFoundError is also what you get for a project this key was scoped away from — the API does not distinguish the two, so key scoping cannot be used to probe what sits behind it.

Keys & security

  • Keys look like qvx-live- plus 28 characters, and the full value is shown once, when you create it. Only a hash is stored, so it cannot be recovered — lose it, revoke it, mint a new one.
  • A key belongs to your account, and can optionally be narrowed to specific projects (or to none) when you create or edit it.
  • A key carries the full rights of your account within its scope, including editing an agent's prompt and deleting documents. Never ship one to a browser, a mobile app, or a public repo. For a chat widget on a website, use the embed snippet on your project's Deployments page — that uses a separate, domain-locked public key designed to be visible.

Requirements

Python 3.8+ and requests. That is the whole dependency list.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qunivex-1.0.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qunivex-1.0.0-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file qunivex-1.0.0.tar.gz.

File metadata

  • Download URL: qunivex-1.0.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.5

File hashes

Hashes for qunivex-1.0.0.tar.gz
Algorithm Hash digest
SHA256 346ac99052920ac11084ceb591ec41d88a40cfc440a79194cbbeeb2312f653cb
MD5 a60b60e4d9a8410b925614d0fd31a6e0
BLAKE2b-256 fe4f49a97a794754a803cb4cf41ff24916ef9d5e548a59b282a9a8e937caa716

See more details on using hashes here.

File details

Details for the file qunivex-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: qunivex-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.5

File hashes

Hashes for qunivex-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cafe53f4693a8ca22996bad61d931d1ae8f88fbe5eab2995a393f3218ca93bdf
MD5 10c9d667d60bcb13d145d3e9f6885d0b
BLAKE2b-256 a8cec6cde797f2fdabdab6057292d0668d0bb23db7f62daed22f10aed7ed738a

See more details on using hashes here.

Release history Release notifications | RSS feed

2.0.0

2 files

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page