dukk
SDK oficial Python para a Dukk Platform API — superfície espelhada do
openai-python, sync + async, única dependência de runtime (httpx).
Instalação
pip install dukk
Requisitos: Python >= 3.10.
Quickstart
from dukk import Dukk
client = Dukk() # ou Dukk(api_key="dukk-...") -- por padrão le DUKK_API_KEY
resp = client.chat.completions.create(
messages=[
{"role": "user", "content": 'Crie um script Python que lê um CSV e imprime a média da coluna "valor".'},
],
dukk={
"deliver": "auto", # artifacts JSON/text inline; binários por referência
"conversation_id": "proj-x", # conversa persistente client-side (opcional)
},
)
print(resp.choices[0].message.content)
for artifact in (resp.dukk.artifacts if resp.dukk else []):
if artifact.data is not None:
print("inline:", artifact.filename, artifact.data)
else:
print("referência:", artifact.id, artifact.filename)
Async
import asyncio
from dukk import AsyncDukk
async def main():
async with AsyncDukk() as client:
resp = await client.chat.completions.create(
messages=[{"role": "user", "content": "Olá!"}],
)
print(resp.choices[0].message.content)
asyncio.run(main())
Autenticação
A API key pode ser configurada de três formas (em ordem de precedência):
- Argumento no construtor:
Dukk(api_key="dukk-...") - Variável de ambiente:
DUKK_API_KEY=dukk-... - Erro claro se ausente em ambos os lugares.
Opções do cliente
client = Dukk(
api_key="dukk-...",
base_url="https://api.dukk.com.br/dukk/compat/v1", # padrão
timeout=300.0, # segundos, padrão 5 min (turnos podem ser longos)
max_retries=2, # retry automático em 5xx / erros de rede
default_headers={"X-My-App": "1.0"},
)
Modelo
O único modelo público é "dukk" (ou omitido). O mix de modelos por baixo é
decisão interna da plataforma — passar qualquer outro valor resulta em
404 model_not_found.
Opções Dukk (bloco dukk)
O bloco dukk no request habilita extensões além do padrão OpenAI:
| Opção | Tipo | Default | Descrição |
|---|---|---|---|
sandbox_id |
str |
"default" |
UUID do sandbox ou "default" |
deliver |
"auto" | "inline" | "reference" |
"auto" |
Política de entrega de artifacts |
conversation_id |
str |
— | Chave client-side de conversa persistente |
Streaming SSE
Nota: streaming requer plano Enterprise. Contato: adm@nexcode.live. Usuários sem o plano recebem
400 streaming_not_supported_yet.
for chunk in client.chat.completions.create(
messages=[{"role": "user", "content": "Escreva um poema."}],
stream=True,
):
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="")
if chunk.dukk:
if "type" in chunk.dukk:
print("\nevento:", chunk.dukk["type"])
elif "event" in chunk.dukk:
print("\nturn_error:", chunk.dukk["error"])
Tabela de erros
Todos os erros são subclasses de DukkError e carregam status, code,
type e param.
| HTTP | code |
Classe |
|---|---|---|
| 400 | missing_messages |
BadRequestError |
| 400 | streaming_not_supported_yet |
BadRequestError |
| 400 | unsupported_parameter |
BadRequestError |
| 400 | invalid_deliver |
BadRequestError |
| 400 | invalid_sandbox_id |
BadRequestError |
| 400 | conversation_required_for_tools |
BadRequestError |
| 401 | invalid_api_key |
AuthenticationError |
| 403 | insufficient_scope |
PermissionDeniedError |
| 404 | model_not_found |
NotFoundError |
| 404 | sandbox_not_found |
NotFoundError |
| 404 | conversation_not_found |
NotFoundError |
| 404 | file_not_found |
NotFoundError |
| 500 | db_error, session_missing |
ServerError |
| 502 | turn_failed |
ServerError |
| 504 | turn_timeout |
ServerError |
from dukk import AuthenticationError, NotFoundError
try:
client.chat.completions.create(messages=[...])
except AuthenticationError as err:
print("API key inválida:", err.code) # invalid_api_key
except NotFoundError as err:
print("Não encontrado:", err.code) # model_not_found | sandbox_not_found
Conversas persistentes (client.conversations)
dukk.conversation_id é uma chave client-side que identifica uma
conversa persistente (classe isolada api_client_only — nunca colide com
conversas desk/web):
# Primeira mensagem
client.chat.completions.create(
messages=[{"role": "user", "content": "Meu projeto se chama Alfa."}],
dukk={"conversation_id": "projeto-alfa"},
)
# Segunda mensagem -- o agente lembra do nome
client.chat.completions.create(
messages=[{"role": "user", "content": "Qual é o nome do meu projeto?"}],
dukk={"conversation_id": "projeto-alfa"},
)
# Gestão da conversa
conv = client.conversations.retrieve("projeto-alfa")
history = client.conversations.messages("projeto-alfa")
artifacts = client.conversations.artifacts("projeto-alfa") # paginação fixa: até 100
client.conversations.delete("projeto-alfa")
Licença
MIT — © Dukk / Nexcode
Release files for dukk 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 | |
|---|---|---|---|
| dukk-0.1.0.tar.gz | 41.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dukk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.0 kB
Release files / dukk-0.1.0.tar.gz
| Download URL | dukk-0.1.0.tar.gz |
|---|---|
| Size | 41.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3af823953227f3a7bcab8822110c68fa1a20e43e12c4eef127be13bb9e533940
|
|
BLAKE2b-256 checksum How to use checksums |
44066d415d40545303db631a4be54198e5e12e5537568e1647abac05cedab0a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / dukk-0.1.0-py3-none-any.whl
| Download URL | dukk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6822304df31e1af61280b9b9b11c406a61cb595f08c342e9f5d0e7fa93b3ed68
|
|
BLAKE2b-256 checksum How to use checksums |
528d529a68547b823ecbe0960c75209e1beb880fa88440754585d7efa43a2639
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|