Skip to main content

Deixic SDK for Python

deixic-sdk is the supported Python client for applications that submit Deixic tasks, follow durable progress, interrupt work, and approve or deny requested actions. It uses binary Connect/protobuf requests rather than the browser-only API.

Install

pip install deixic-sdk

Quickstart

import os

from deixic import Deixic

deixic = Deixic(
    api_key=os.environ["DEIXIC_API_KEY"],
    organization_id="org_123",
    workspace_id="ws_456",
)

task = deixic.tasks.start(
    channel_id="company",
    body="Review the open changes.",
    idempotency_key="review-request-001",  # Stable business-event ID for this request.
)

result = task.wait(timeout=60)
if result.status == "completed":
    print(result.body)
else:
    print(result.status, result.reason)

Choose a different key for each new business request. Recovery of the same request keeps its original key and body. Submission proves acceptance. task.wait() follows durable events and returns the final assistant answer linked to that accepted turn, together with its referenced receipts.

Task handles and setup checks

deixic.tasks.check_setup(channel_id="company") makes one read request to verify channel access and reports the owner's workspace prerequisites and selected/default model availability. accessible confirms read access; write_access remains not_checked. The report contains next_action and, on failure, an SDK error with its request ID. Submission checks write authorization and execution.

For restart recovery, use tasks.prepare(..., on_checkpoint=save_checkpoint) with your application's storage adapter, then task.submit(). The callback runs before submission and after acceptance or consumed event pages. Storage errors propagate. tasks.resume(saved_checkpoint) restores observation coordinates and never submits work. task.replay() explicitly repeats an unacknowledged request with its original body, key, tenant and origin; it refuses an accepted task.

Checkpoints use the shared Python/TypeScript deixic.task.v1 format with decimal-string int64 cursors. They contain the request body and no SDK credential. Protect them as customer data and use one observer/storage writer per checkpoint. A checkpoint never proves authorization or task completion.

wait() uses bounded event backfill and polling, reconnecting read requests after transport/unavailable failures up to max_reconnect_attempts. It never retries a mutation. timeout is the observation budget; each read timeout is capped by the remaining budget, subject to the transport's timeout semantics. cancelled=lambda: ... stops local observation. Remote interruption requires an explicit controls.interrupt() call.

wait() continues past a preliminary responded state until completion, failure, interruption or work that needs attention. result() reads the current owner state once. Outcomes are completed, responded, waiting, failed, interrupted, unfinished, prepared, or unacknowledged. A waiting outcome includes its turn's waiting reason and a freshly retrieved request event when retained. Use that event's request identity with controls.respond() after an explicit application/user decision. Missing request history stays waiting/request_not_visible; no approval is invented or sent automatically. Progress callbacks receive only new matching-turn events. Callbacks may be delivered again after a storage failure or restart; make application effects idempotent. Callback exceptions propagate.

result.parse(your_parser) validates/converts the completed answer using your application's schema. Parser failures propagate. A completed answer does not prove that every external action succeeded; inspect the receipts' owner-resolved lifecycle and evidence for those actions.

Account-brief workflow

Use a workspace with connected CRM data and a policy that permits only CRM reads for this workflow. The SDK creates no connector, grant or model route. The example asks for a summary, open opportunities, risks and source references; Platform enforces the workspace's access and action policy.

Set the three DEIXIC_* variables used above, then run the installed example:

python -m deixic.examples.account_brief check --channel company
python -m deixic.examples.account_brief start account-brief.json \
  --channel company --account 'Example account' --trigger crm-event-001
# A separate process retrieves the result:
python -m deixic.examples.account_brief resume account-brief.json

start saves a private checkpoint before sending and reports acceptance. resume prints the final brief and receipt IDs when completed. It returns exit code 2 for unfinished work or work that needs attention. If acceptance was lost, explicitly run replay account-brief.json, then resume. A new start refuses an existing checkpoint path. The same file can be resumed by the TypeScript account-brief example with the same tenant and origin.

Add --structured to start to request the versioned JSON brief and validate facts against its declared source IDs. A restarted worker remembers the saved format. resume --progress writes matching event IDs to stderr and the final JSON to stdout. Missing CRM data is explicit; malformed results return exit 2 with invalid_result, without another submission. Receipt owner, object, lifecycle and evidence references appear separately in actions. A completed answer with a failed or unavailable receipt still returns exit 2.

The installed example also supports explicit approve and deny commands with --request and --decision-key. They re-fetch the current owner request; Platform checks the operator's authorization. Observation never approves work. See the complete application guide for the trigger/worker integration, result format, approval decisions, receipt interpretation and tested recovery cases. The private-file storage example requires a POSIX filesystem supporting atomic rename, hard links and fsync; hosted applications use their existing durable storage and job queue.

Submit and recover a final result

Create a Deixic tasks token in Settings → API access and keep it in your server-side secret manager. Set DEIXIC_API_KEY, DEIXIC_ORGANIZATION_ID, and DEIXIC_WORKSPACE_ID for that tenant. DEIXIC_BASE_URL defaults to https://app.deixic.com; use an explicit URL for a test environment.

The installed package includes a runnable example:

python -m deixic.examples.task_result start task.json \
  --channel company --body 'Review the open changes.'

It saves the request body, tenant, Platform URL, and idempotency key before submission. After acceptance it saves the turn ID and replay cursor, then backfills events, watches progress, and fetches the final assistant message linked to that turn and any referenced receipts. Preliminary answers and another turn's completion do not establish success. Exit code 0 means the matching turn completed; code 2 means unfinished, failed, interrupted, or unacknowledged; code 1 reports an SDK error.

After a process restart or stream closure, resume observation:

python -m deixic.examples.task_result resume task.json

resume never submits work. It uses the saved cursor, and replaces its turn projection from the owner snapshot when retention requires a reset. A stream closing without matching completion remains unfinished/watch_eof.

If the submission response was lost, the checkpoint may have no accepted turn ID. Explicitly replay the original saved request:

python -m deixic.examples.task_result replay task.json

Replay reuses the original request body and idempotency key; it refuses an already accepted checkpoint. Do not start again with a new key to recover the same request. A checkpoint cannot be moved to a different tenant or Platform URL. Its file permissions are restricted to the current user, it contains no credential, and it must still be protected because it contains the task body. Use one process per checkpoint. This example does not run tools or approve actions automatically; waiting work retains the owner's state.

Verify against a real test tenant

The package also includes deixic.examples.verify_test_journey. Supply an explicit dedicated test tenant, its task token, DEIXIC_BASE_URL, DEIXIC_IDENTITY_API_KEY_VALIDATE_URL (Identity's /v1/api-keys/validate), and DEIXIC_TEST_CHANNEL_ID, in addition to the organization/workspace variables above. The probe self-introspects the supplied key with Identity and requires task read/write grants in the expected organization. Platform still owns workspace authorization and execution; the probe grants no access.

python -m deixic.examples.verify_test_journey submit journey.json
# The first process exits after acceptance. Start a separate recovery process:
python -m deixic.examples.verify_test_journey resume journey.json

The second process reloads the checkpoint, creates a new client, and verifies the matching turn's final linked message against a unique harmless request. Its receipt omits the token, prompt, and generated body. It returns nonzero for unfinished work, denied Identity grants, or mismatched output. This opt-in probe does not provision tenants or credentials, and must not be pointed at a customer workspace. Running fixture tests does not establish this live proof.

For an automated run with that explicit configuration:

DEIXIC_REAL_JOURNEY=1 python -m pytest -q \
  sdk/deixic/python/tests/test_real_journey.py

That acceptance test launches submission and recovery in separate processes. It is skipped in ordinary unit CI because it requires real test-tenant services.

The organization and workspace are fixed when the client is created. Every request carries both values in the typed query and request headers. Mutations require caller-owned idempotency keys. Mutation methods do not retry unavailable or transport failures; task observation has the bounded read recovery described above.

Use API keys only from trusted server-side applications. Rotating workloads can provide a CredentialProvider; an authentication replay is allowed only when the refreshed credential retains the same subject, tenant, and declared scopes.

Coding output readback

messages.send(coding_acceptance=contract) sends the typed coding contract and marks the request as coding implementation. contract.output_paths can select up to eight UTF-8 files whose contents differ from the admitted baseline (or are newly added), totaling at most 64 KiB, for native completion capture. Completion reads those files from the clean committed Git revision; caller-provided output bytes are not a completion input.

Native validation authenticates the candidate commit and trees, then compares all tracked physical bytes and executable modes with committed blobs. It does not trust Git's cached clean status or run clean filters. Paths must be UTF-8; symlinks must resolve into the authenticated tracked tree. Submodules, dangling or external symlinks, and missing local Git objects fail validation. Missing objects are not fetched during validation.

This check supports up to 100,000 tracked entries and 100,000 tree objects, 256 directory levels, 64 MiB per tracked blob, and 512 MiB of tracked content. Commit objects are limited to 1 MiB and individual tree objects to 16 MiB. These source-verification limits also apply when output_paths is omitted; output publication remains optional. The separate 64 KiB output limit applies to the new output bytes, so a larger baseline file may shrink to a valid output.

When Platform accepts the runtime's coding proof, the work receipt can contain coding_acceptance, including its work/run, originating actor, commit, and immutable VFS version and SHA-256 for each output. Request the bytes explicitly:

receipt = deixic.receipts.get(
    channel_id=channel_id,
    receipt_id=receipt_id,
    include_coding_output_content=True,
).receipt

The read requires the originating actor and exact tenant scope. Ordinary thread and receipt responses omit output bytes. A consumer must compare the returned bytes against its own acceptance criteria; a completed turn or an artifact reference alone does not prove the requested result.

These APIs do not provision execution capabilities. The hosted Operating runner currently grants external Computer tools and excludes native coding_task and Bash. Its Computer sandbox and the native coding checkout are separate owners; this output contract alone does not make hosted coding qualification available.

Recovery

Start with deixic.threads.get(), retain replay_cursor, and backfill with deixic.events.list(). If an event page sets reset_required, replace the local projection with its supplied snapshot and authoritative thread_execution.replay_cursor. deixic.events.watch() yields bounded protobuf pages from one server stream; the caller decides reconnection and resumes from the last saved cursor.

Public protocol boundary

This package includes only the deixicpublic.v1.DeixicPublicService contract and its standard protobuf dependencies. Read responses expose public thread, message, event, setup, and receipt projections. Receipt evidence uses public resource references; service ownership and internal execution records are not part of this contract. Pagination uses page tokens.

Existing deixic.task.v1 checkpoints remain readable, including accepted turn IDs and decimal-string cursors. Their channelId identifies the public thread. Python message types are available from deixic.protocol; TypeScript exports public message types and schemas from the package root. Existing TypeScript operating-type names are aliases of these public types.

Release files for deixic-sdk 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for deixic-sdk 0.1.6
File Size Uploaded
deixic_sdk-0.1.6.tar.gz 59.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deixic-sdk 0.1.6
File Interpreter ABI Platform
deixic_sdk-0.1.6-py3-none-any.whl Python 3 none any Details

Total release size: 100.4 kB

Release files / deixic_sdk-0.1.6.tar.gz

Download URL deixic_sdk-0.1.6.tar.gz
Size 59.6 kB
Tags Source
SHA-256 checksum
How to use checksums
da7d013f40028afa85a9a7687cedb1691484b6f0de66322f94323ac93c46db25
BLAKE2b-256 checksum
How to use checksums
7e95a1df704a7c25ca0163caa319ed1866715ce1805d8fd8aed1beeff92d395c
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 Sep 24, 2026.

Transparency log

Release files / deixic_sdk-0.1.6-py3-none-any.whl

Download URL deixic_sdk-0.1.6-py3-none-any.whl
Size 40.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a954657dba9dbe7222138a2c405faedc727eb015416e39c73390054329f3f96c
BLAKE2b-256 checksum
How to use checksums
56464acfab7e7bdf8f8d42d0c907c6f851dd169ae987b4a46ad0054f9b7161ac
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 Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.6 This release

2 release 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